Esempio n. 1
0
    def declareAttackers(self, opponents):
        multiple_opponents = len(opponents) > 1
        all_on_attacking_side = self.battlefield.get(isCreature)
        invalid_attack = True
        prompt = "Declare attackers (Enter to accept, Escape to reset)"
        while invalid_attack:
            attackers = set()
            done_selecting = False
            creature = self.getCombatCreature(mine=True, prompt=prompt)
            while not done_selecting:
                if creature == True:
                    done_selecting = True
                    break
                elif creature == False:
                    self.send(AttackersResetEvent())
                    break
                else:
                    if not creature in attackers and creature.canAttack():
                        attackers.add(creature)
                        self.send(AttackerSelectedEvent(), attacker=creature)

                        # Now select who to attack
                        if multiple_opponents:
                            while True:
                                target = self.getTarget(target_types=(OpponentMatch(self), isPlaneswalker), zone="battlefield", prompt="Select opponent to attack")
                                if target in opponents:
                                    creature.setOpponent(target)
                                    break
                                else: prompt = "Can't attack %s. Select again"%target
                        else: creature.setOpponent(opponents[0])
                        prompt = "%s selected - select another"%creature
                    elif creature in attackers:
                        self.send(InvalidTargetEvent(), target=creature)
                        prompt = "%s already in combat - select another"%creature
                    else:
                        self.send(InvalidTargetEvent(), target=creature)
                        prompt = "%s cannot attack - select another"%creature
                creature = self.getCombatCreature(mine=True, prompt=prompt)

            if done_selecting:
                not_attacking = set(all_on_attacking_side)-attackers
                invalid_attackers = [creature for creature in all_on_attacking_side if not creature.checkAttack(attackers, not_attacking)] + [creature for creature in attackers if not creature.computeAttackCost()]
                invalid_attack = len(invalid_attackers) > 0
                if not invalid_attack:
                    for creature in attackers:
                        creature.payAttackCost()
                        creature.setAttacking()
                else:
                    prompt = "Invalid attack - choose another"
                    for creature in invalid_attackers: self.send(InvalidTargetEvent(), target=creature)
            else: prompt = "Declare attackers (Enter to accept, Escape to reset)"
        return list(attackers)
Esempio n. 2
0
 def choose_from_zone(self, number=1, cardtype=isCard, zone="battlefield", action='', required=True, all=False):
     cards_in_zone = getattr(self, zone).get(cardtype)
     if zone == "library" and not cardtype == isCard: required = False
     if len(cards_in_zone) == 0 and not zone == "library": cards = []
     elif number >= len(cards_in_zone) and required: cards = cards_in_zone
     else:
         cards = []
         if zone == "battlefield" or zone == "hand":
             a = 's' if number > 1 else ''
             total = number
             prompt = "Select %s%s to %s: %d left of %d"%(cardtype, a, action, number, total)
             while number > 0:
                 card = self.getTarget(cardtype, zone=zone, from_player=None if all else "you", required=required, prompt=prompt)
                 if card == False: break
                 if card in cards:
                     prompt = "Card already selected - select again"
                     self.send(InvalidTargetEvent(), target=card)
                 else:
                     cards.append(card)
                     number -= 1
                     prompt = "Select %s%s to %s: %d left of %d"%(cardtype, a, action, number, total)
         else:
             selection = list(getattr(self, zone))
             if number >= -1:
                 if number == 1: a = 'a'
                 elif number == -1: a = 'any number of'
                 else: a = str(number)
                 cards = self.getCardSelection(selection, number=number, cardtype=cardtype, required=required, prompt="Search your %s for %s %s to %s."%(zone, a, cardtype, action))
                 if zone == "library": self.shuffle()
     return cards
Esempio n. 3
0
        def filter(action):
            if isinstance(action, CancelAction) or isinstance(action, PassPriority):
                return action

            target = action.selection
            if isCreature(target) and ((mine and target.controller == self) or
                (not mine and target.controller in self.opponents)): return target
            else:
                self.send(InvalidTargetEvent(), target=target)
                return False
Esempio n. 4
0
        def filter(action):
            if isinstance(action, CancelAction) or isinstance(action, PassPriority):
                return action

            card = action.selection
            if isPermanent(card) and (card.controller == self):
                return card
            else:
                self.send(InvalidTargetEvent(), target=card)
                return False
Esempio n. 5
0
        def filter(action):
            # This function is really convoluted
            # If I return False here then the input function will keep cycling until valid input
            if isinstance(action, CancelAction):
                if not required: return action
                else: return False
            elif isinstance(action, PassPriority): return False

            target = action.selection
            if isPlayer(target) or ((not zone or str(target.zone) == zone) and (not from_player or (from_player == "you" and target.controller == self) or (from_player == "opponent" and target.controller in self.opponents))):
                for target_type in target_types:
                    if target_type(target): return target
            # Invalid target
            self.send(InvalidTargetEvent(), target=target)
            return False
Esempio n. 6
0
 def untapStep(self):
     permanents = untapCards = set([card for card in self.battlefield if card.canUntapDuringUntapStep()])
     prompt = "Select cards to untap"
     valid_untap = self.checkUntapStep(permanents)
     while not valid_untap:
         permanents = set()
         done_selecting = False
         perm = self.getPermanentOnBattlefield(prompt=prompt)
         while not done_selecting:
             if perm == True:
                 done_selecting = True
                 self.send(AllDeselectedEvent())
                 break
             elif perm == False:
                 # reset untap
                 permanents = untapCards
                 self.send(AllDeselectedEvent())
                 prompt = "Selection canceled - select cards to untap"
                 break
             else:
                 if not perm in permanents and perm in untapCards:
                     permanents.add(perm)
                     self.send(CardSelectedEvent(), card=perm)
                     prompt = "%s selected - select another"%perm
                 elif perm in permanents:
                     self.send(InvalidTargetEvent(), target=perm)
                     prompt = "%s already selected - select another"%perm
                 else:
                     self.send(InvalidTargetEvent(), target=perm)
                     prompt = "%s can't be untapped - select another"%perm
             perm = self.getPermanentOnBattlefield(prompt=prompt)
         if done_selecting:
             valid_untap = self.checkUntapStep(permanents)
             if not valid_untap:
                 prompt = "Invalid selection - select again"
     for card in permanents: card.untap()
Esempio n. 7
0
 def reorderBlockers(self, combat_assignment):
     blocker_sets = {}
     do_reorder = False
     for attacker, blockers in combat_assignment.items():
         if len(blockers) > 1:
             for blocker in blockers: blocker_sets[blocker] = (attacker, blockers)
             do_reorder = True
     if do_reorder:
         prompt = "Order blockers (enter to accept)"
         # Select blocker
         while True:
             blocker = self.getCombatCreature(mine=False, prompt=prompt)
             if blocker == True: # Done reordering
                 break
             elif blocker == False: pass
             elif blocker in blocker_sets:
                 attacker, blockers = blocker_sets[blocker]
                 i = blockers.index(blocker)
                 blockers[:] = [blocker] + blockers[:i] + blockers[i+1:]
                 self.send(BlockersReorderedEvent(), attacker=attacker, blockers=blockers)
             else:
                 self.send(InvalidTargetEvent(), target=blocker)
                 prompt = "Invalid creature. Select blocker"
     return combat_assignment
Esempio n. 8
0
    def declareBlockers(self, attackers):
        combat_assignment = dict([(attacker, []) for attacker in attackers])
        # Make sure you have creatures to block
        all_on_blocking_side = self.battlefield.get(isCreature)
        if len(all_on_blocking_side) == 0: return combat_assignment

        invalid_block = True
        blocker_prompt = "Declare blockers (Enter to accept, Escape to reset)"
        while invalid_block:
            total_blockers = set()
            done_selecting = False
            while not done_selecting:
                blocker = self.getCombatCreature(mine=True, prompt=blocker_prompt)
                if blocker == True:
                    done_selecting = True
                    break
                elif blocker == False:
                    # Reset the block
                    self.send(BlockersResetEvent())
                    combat_assignment = dict([(attacker, []) for attacker in attackers])
                    break
                else:
                    if blocker in total_blockers or not blocker.canBlock():
                        if blocker in total_blockers: reason = "already blocking"
                        elif not blocker.canBlock(): reason = "can't block"
                        self.send(InvalidTargetEvent(), target=blocker)
                        blocker_prompt = "%s %s - select another blocker"%(blocker, reason)
                    else:
                        # Select attacker
                        valid_attacker = False
                        attacker_prompt = "Select attacker to block"
                        while not valid_attacker:
                            attacker = self.getCombatCreature(mine=False, prompt=attacker_prompt)
                            if attacker == True: pass # XXX What does enter mean here?
                            elif attacker == False: break # Pick a new blocker
                            elif attacker.attacking and attacker.canBeBlocked() and blocker.canBlockAttacker(attacker) and attacker.canBeBlockedBy(blocker):
                                valid_attacker = True
                                total_blockers.add(blocker)
                                combat_assignment[attacker].append(blocker)
                                self.send(BlockerSelectedEvent(), attacker=attacker, blocker=blocker)
                                attacker_prompt = "Select attacker to block"
                                blocker_prompt = "Declare blockers (Enter to accept, Escape to reset)"
                            else:
                                if not attacker.attacking: reason = "cannot block non attacking %s"%attacker
                                else: reason = "cannot block %s"%attacker
                                self.send(InvalidTargetEvent(), target=blocker)
                                self.send(InvalidTargetEvent(), target=attacker)
                                attacker_prompt = "%s %s - select a new attacker"%(blocker,reason)

            if done_selecting:
                nonblockers = set(all_on_blocking_side)-total_blockers
                invalid_blockers = [creature for creature in attackers+all_on_blocking_side if not creature.checkBlock(combat_assignment, nonblockers)] + [creature for creature in total_blockers if not creature.computeBlockCost()]
                invalid_block = len(invalid_blockers) > 0
                if not invalid_block:
                    for attacker, blockers in combat_assignment.items():
                        if blockers:
                            attacker.setBlocked(blockers)
                            for blocker in blockers:
                                blocker.payBlockCost()
                                blocker.setBlocking(attacker)
                else:
                    blocker_prompt = "Invalid defense - choose another"
                    for creature in invalid_blockers: self.send(InvalidTargetEvent(), target=creature)
            else: blocker_prompt = "Declare blockers (Enter to accept, Escape to reset)"

        return combat_assignment