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)
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
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
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
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
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()
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
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