@Override public boolean apply(Game game, Ability source) { boolean result = false; Player graveyardPlayer = null; for (UUID cardInGraveyard : targetPointer.getTargets(game, source)) { Card card = game.getCard(cardInGraveyard); if (card != null) { for (Player player : game.getPlayers().values()) { if (player.getGraveyard().contains(card.getId())) { graveyardPlayer = player; player.getGraveyard().remove(card); result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); } } } } Card card = game.getCard(source.getSourceId()); result |= card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); Player player = game.getPlayer(card.getOwnerId()); if (player != null) { player.shuffleLibrary(game); } if (graveyardPlayer != null && !graveyardPlayer.equals(player)) { graveyardPlayer.shuffleLibrary(game); } return result; }
@Override public boolean apply(Game game, Ability source) { UUID exileId = CardUtil.getCardExileZoneId(game, source); for (UUID opponentId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(opponentId); if (opponent != null) { Cards cards = new CardsImpl(); cards.addAll(opponent.getHand()); for (UUID cardId : cards) { Card card = game.getCard(cardId); if (card != null) { card.moveToExile(exileId, "Ashiok, Nightmare Weaver", source.getSourceId(), game); } } cards.clear(); cards.addAll(opponent.getGraveyard()); for (UUID cardId : cards) { Card card = game.getCard(cardId); if (card != null) { card.moveToExile(exileId, "Ashiok, Nightmare Weaver", source.getSourceId(), game); } } } } return true; }
@Override public boolean apply(Game game, Ability source) { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card != null) { PutTokenOntoBattlefieldCopyTargetEffect effect = new PutTokenOntoBattlefieldCopyTargetEffect( source.getControllerId(), CardType.ARTIFACT, true); effect.setTargetPointer( new FixedTarget(card.getId(), game.getState().getZoneChangeCounter(card.getId()))); effect.apply(game, source); for (Permanent addedToken : effect.getAddedPermanent()) { SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect( "Sacrifice the token at the beginning of the next end step", source.getControllerId()); sacrificeEffect.setTargetPointer(new FixedTarget(addedToken, game)); DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrificeEffect); game.addDelayedTriggeredAbility(delayedAbility, source); } return true; } return false; }
@Override public boolean apply(Game game, Ability source) { RevealTargetFromHandCost revealCost = null; for (Cost cost : source.getCosts()) { if (cost instanceof RevealTargetFromHandCost) { revealCost = (RevealTargetFromHandCost) cost; } } Player controller = game.getPlayer(source.getControllerId()); Card sourceCard = game.getCard(source.getSourceId()); if (controller != null && sourceCard != null && revealCost != null) { int live = revealCost.getNumberRevealedCards() * 3; if (live > 0) { controller.gainLife(live, game); } game.informPlayers( new StringBuilder(sourceCard.getName()) .append(": ") .append(controller.getName()) .append(" revealed ") .append(revealCost.getNumberRevealedCards()) .append(revealCost.getNumberRevealedCards() == 1 ? "white card" : "white cards") .append(" and gained ") .append(live) .append(" live") .toString()); return true; } return false; }
@Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { FilterCard filter = new FilterCard("red instant or sorcery card from your graveyard to play"); filter.add(new ColorPredicate(ObjectColor.RED)); filter.add( Predicates.or( new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); String message = "Play red instant or sorcery card from your graveyard without paying its mana cost?"; Set<Card> cards = player.getGraveyard().getCards(filter, game); TargetCardInGraveyard target = new TargetCardInGraveyard(filter); while (!cards.isEmpty() && player.chooseUse(outcome, message, source, game)) { target.clearChosen(); if (player.choose(outcome, target, source.getSourceId(), game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { player.cast(card.getSpellAbility(), game, true); player.getGraveyard().remove(card); cards.remove(card); } } } return true; } return false; }
@Override public boolean apply(Game game, Ability source) { if (onCard) { Card card; if (affectedObjectsSet) { card = affectedObjectList.get(0).getCard(game); } else { card = game.getCard(source.getSourceId()); } if (card != null) { // add ability to card only once game.getState().addOtherAbility(card, ability); return true; } } else { Permanent permanent; if (affectedObjectsSet) { permanent = affectedObjectList.get(0).getPermanent(game); } else { permanent = game.getPermanent(source.getSourceId()); } if (permanent != null) { permanent.addAbility(ability, source.getSourceId(), game, false); return true; } } if (duration.equals(Duration.Custom)) { this.discard(); } return true; }
@Override public boolean apply(Game game, Ability source) { Set<String> targets = new HashSet<>(); for (UUID target : targetPointer.getTargets(game, source)) { Permanent permanent = game.getPermanent(target); if (permanent != null) { permanent.untap(game); targets.add(CardUtil.getCardZoneString("", permanent.getId(), game)); } } if (!targets.isEmpty()) { // save the targets for the watcher in a map with zone change counter (as the card is recast // during combat it's neccessary to save with zone change counter) Map<Integer, Set<String>> targetMap; Object object = game.getState().getValue("targets" + source.getSourceId()); if (object != null && object instanceof Map) { targetMap = (Map<Integer, Set<String>>) object; } else { targetMap = new HashMap<>(); } targetMap.put(game.getCard(source.getSourceId()).getZoneChangeCounter(game), targets); if (object == null) { game.getState().setValue("targets" + source.getSourceId().toString(), targetMap); } } return true; }
@Override public void init(Game game, Ability source) { Card card = game.getCard(target); if (card != null) { this.zoneChangeCounter = card.getZoneChangeCounter(game); } }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { Player damagedPlayer = game.getPlayer(targetPointer.getFirst(game, source)); if (damagedPlayer == null) { return false; } FilterCard filter = new FilterCard( "target instant or sorcery card from " + damagedPlayer.getName() + "'s graveyard"); filter.add(new OwnerIdPredicate(damagedPlayer.getId())); filter.add( Predicates.or( new CardTypePredicate(CardType.INSTANT), new CardTypePredicate(CardType.SORCERY))); Target target = new TargetCardInGraveyard(filter); if (controller.chooseTarget(Outcome.PlayForFree, target, source, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { controller.cast(card.getSpellAbility(), game, true); game.addEffect(new WrexialReplacementEffect(card.getId()), source); } } return true; } return false; }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = (Permanent) game.getLastKnownInformation(target, Zone.BATTLEFIELD); if (permanent != null && controller != null) { Player player = game.getPlayer(permanent.getOwnerId()); if (player != null) { FilterCreatureCard filter = new FilterCreatureCard( new StringBuilder("a creature card from ") .append(player.getLogName()) .append("'s graveyard") .toString()); filter.add(new OwnerIdPredicate(player.getId())); Target targetCreature = new TargetCardInGraveyard(filter); if (targetCreature.canChoose(source.getSourceId(), controller.getId(), game) && controller.chooseTarget(outcome, targetCreature, source, game)) { Card card = game.getCard(targetCreature.getFirstTarget()); if (card != null && game.getState().getZone(card.getId()).equals(Zone.GRAVEYARD)) { return card.putOntoBattlefield( game, Zone.GRAVEYARD, source.getSourceId(), player.getId()); } } return true; } } return false; }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (controller != null && sourceObject != null) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); UUID exileId = CardUtil.getExileZoneId( game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); if (permanent != null) { return controller.moveCardToExileWithInfo( permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); } else { Card card = game.getCard(getTargetPointer().getFirst(game, source)); if (card != null) { return controller.moveCardToExileWithInfo( card, exileId, sourceObject.getIdName(), source.getSourceId(), game, game.getState().getZone(card.getId()), true); } } } return false; }
@Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { if (permanent.getImprinted().size() > 0) { Card card = game.getCard(permanent.getImprinted().get(0)); if (card != null && card.getCardType().contains(CardType.CREATURE)) { switch (layer) { case TypeChangingEffects_4: if (sublayer == SubLayer.NA) { permanent.getSubtype().addAll(card.getSubtype()); } break; case PTChangingEffects_7: if (sublayer == SubLayer.SetPT_7b) { permanent.getPower().setValue(card.getPower().getValue()); permanent.getToughness().setValue(card.getToughness().getValue()); } } return true; } } } return false; }
@Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if ((abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility)) { Card sourceCard = game.getCard(abilityToModify.getSourceId()); return sourceCard != null && this.filter.match(sourceCard, game); } return false; }
@Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Card card = game.getCard(source.getFirstTarget()); if (card != null) { card.moveToExile(null, "", source.getId(), game); } return true; }
@Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) { Card c = game.getCard(event.getTargetId()); if (c != null && c.getCardType().contains(CardType.CREATURE)) return true; } return false; }
@Override public boolean applies(Ability abilityToModify, Ability source, Game game) { if ((abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) && abilityToModify.getControllerId().equals(source.getControllerId())) { Card card = game.getCard(abilityToModify.getSourceId()); return card.getName().equals(game.getState().getValue(source.getSourceId().toString())); } return false; }
@java.lang.Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); Player player = game.getPlayer(source.getControllerId()); if (permanent != null && player != null) { List<UUID> imprinted = permanent.getImprinted(); if (imprinted.size() > 0) { Card imprintedCard = game.getCard(imprinted.get(0)); if (imprintedCard != null) { Choice choice = new ChoiceImpl(true); choice.setMessage("Pick a mana color"); ObjectColor color = imprintedCard.getColor(game); if (color.isBlack()) { choice.getChoices().add("Black"); } if (color.isRed()) { choice.getChoices().add("Red"); } if (color.isBlue()) { choice.getChoices().add("Blue"); } if (color.isGreen()) { choice.getChoices().add("Green"); } if (color.isWhite()) { choice.getChoices().add("White"); } if (choice.getChoices().size() > 0) { Mana mana = new Mana(); if (choice.getChoices().size() == 1) { choice.setChoice(choice.getChoices().iterator().next()); } else { player.choose(outcome, choice, game); } if (choice.getChoice().equals("Black")) { player.getManaPool().addMana(Mana.BlackMana, game, source); } else if (choice.getChoice().equals("Blue")) { player.getManaPool().addMana(Mana.BlueMana, game, source); } else if (choice.getChoice().equals("Red")) { player.getManaPool().addMana(Mana.RedMana, game, source); } else if (choice.getChoice().equals("Green")) { player.getManaPool().addMana(Mana.GreenMana, game, source); } else if (choice.getChoice().equals("White")) { player.getManaPool().addMana(Mana.WhiteMana, game, source); } else if (choice.getChoice().equals("Colorless")) { player.getManaPool().addMana(Mana.ColorlessMana, game, source); } checkToFirePossibleEvents(mana, game, source); player.getManaPool().addMana(mana, game, source); } } } } return true; }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (controller == null || sourcePermanent == null) { return false; } for (UUID playerId : controller.getInRange()) { Player player = game.getPlayer(playerId); String playerName = new StringBuilder(player.getLogName()).append("'s").toString(); if (source.getControllerId().equals(player.getId())) { playerName = "your"; } TargetCardInLibrary target = new TargetCardInLibrary( new FilterNonlandCard( new StringBuilder("nonland card from ") .append(playerName) .append(" library") .toString())); if (controller.searchLibrary(target, game, playerId)) { UUID targetId = target.getFirstTarget(); Card card = player.getLibrary().remove(targetId, game); if (card != null) { controller.moveCardToExileWithInfo( card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); } } player.shuffleLibrary(game); } ExileZone jaceExileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); if (jaceExileZone == null) { return true; } FilterCard filter = new FilterCard("card to cast without mana costs"); TargetCardInExile target = new TargetCardInExile(filter, source.getSourceId()); while (jaceExileZone.count(filter, game) > 0 && controller.choose(Outcome.PlayForFree, jaceExileZone, target, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { if (controller.cast(card.getSpellAbility(), game, true)) { game.getExile().removeCard(card, game); } } target.clearChosen(); } return true; }
@Override public boolean apply(Game game, Ability source) { boolean isMountain = false; Card sourceCard = game.getCard(source.getSourceId()); Player player = game.getPlayer(source.getControllerId()); if (player == null || sourceCard == null) { return false; } Cards cards = new CardsImpl(Zone.PICK); while (player.getLibrary().size() > 0) { Card card = player.getLibrary().removeFromTop(game); if (card != null) { cards.add(card); if (card.getCardType().contains(CardType.LAND)) { if (card.getSubtype().contains("Mountain")) { isMountain = true; } break; } } else { break; } } player.revealCards(sourceCard.getName(), cards, game); int damage = cards.size(); if (isMountain == true) { damage *= 2; } Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); if (permanent != null) { permanent.damage(damage, source.getSourceId(), game, true, false); } else { Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); if (targetPlayer != null) { targetPlayer.damage(damage, source.getSourceId(), game, false, true); } } TargetCard target = new TargetCard(Zone.PICK, new FilterCard("card to put on the bottom of your library")); target.setRequired(true); while (cards.size() > 1) { player.choose(Outcome.Neutral, cards, target, game); Card card = cards.get(target.getFirstTarget(), game); if (card != null) { cards.remove(card); card.moveToZone(Zone.PICK, source.getId(), game, false); } target.clearChosen(); } return true; }
/** * Checks all available splice effects to be applied. * * @param abilityToModify * @param game */ public void applySpliceEffects(Ability abilityToModify, Game game) { if (((SpellAbility) abilityToModify).getSpellAbilityType().equals(SpellAbilityType.SPLICE)) { // on a spliced ability of a spell can't be spliced again return; } List<SpliceCardEffect> spliceEffects = getApplicableSpliceCardEffects(game, abilityToModify.getControllerId()); // get the applyable splice abilities List<SpliceOntoArcaneAbility> spliceAbilities = new ArrayList<>(); for (SpliceCardEffect effect : spliceEffects) { HashSet<Ability> abilities = spliceCardEffects.getAbility(effect.getId()); for (Ability ability : abilities) { if (effect.applies(abilityToModify, ability, game)) { spliceAbilities.add((SpliceOntoArcaneAbility) ability); } } } // check if player wants to use splice if (spliceAbilities.size() > 0) { Player controller = game.getPlayer(abilityToModify.getControllerId()); if (controller.chooseUse(Outcome.Benefit, "Splice a card?", game)) { Cards cardsToReveal = new CardsImpl(); do { FilterCard filter = new FilterCard("a card to splice"); ArrayList<Predicate<MageObject>> idPredicates = new ArrayList<>(); for (SpliceOntoArcaneAbility ability : spliceAbilities) { idPredicates.add(new CardIdPredicate((ability.getSourceId()))); } filter.add(Predicates.or(idPredicates)); TargetCardInHand target = new TargetCardInHand(filter); controller.chooseTarget(Outcome.Benefit, target, abilityToModify, game); UUID cardId = target.getFirstTarget(); if (cardId != null) { SpliceOntoArcaneAbility selectedAbility = null; for (SpliceOntoArcaneAbility ability : spliceAbilities) { if (ability.getSourceId().equals(cardId)) { selectedAbility = ability; break; } } if (selectedAbility != null) { SpliceCardEffect spliceEffect = (SpliceCardEffect) selectedAbility.getEffects().get(0); spliceEffect.apply(game, selectedAbility, abilityToModify); cardsToReveal.add(game.getCard(cardId)); spliceAbilities.remove(selectedAbility); } } } while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", game)); controller.revealCards("Spliced cards", cardsToReveal, game); } } }
@Override public boolean applies(UUID sourceId, Ability source, Game game) { Card card = game.getCard(sourceId); if (card != null) { if (card.getCardType().contains(CardType.SORCERY) && card.getOwnerId().equals(source.getControllerId())) { return true; } } return false; }
@Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(controllerId).contains(event.getPlayerId())) { Card card = game.getCard(event.getSourceId()); if (card != null && card.getCardType().contains(CardType.CREATURE)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId())); return true; } } return false; }
@Override public boolean apply(Game game, Ability source) { ExileZone exile = game.getExile().getExileZone(exileId); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && exile != null) { if (zone == Zone.GRAVEYARD) { controller.moveCards(exile, zone, Zone.EXILED, source, game); } else { exile = exile.copy(); for (UUID cardId : exile) { Card card = game.getCard(cardId); Player owner = game.getPlayer(card.getOwnerId()); if (owner != null) { switch (zone) { case BATTLEFIELD: card.moveToZone(zone, source.getSourceId(), game, tapped); if (!game.isSimulation()) { game.informPlayers( controller.getLogName() + " moves " + card.getLogName() + " to " + zone.toString().toLowerCase()); } break; case HAND: controller.moveCards(card, Zone.EXILED, Zone.HAND, source, game); break; case LIBRARY: controller.moveCardToLibraryWithInfo( card, source.getSourceId(), game, Zone.EXILED, true, true); break; case GRAVEYARD: controller.moveCards(card, Zone.EXILED, Zone.GRAVEYARD, source, game); break; default: card.moveToZone(zone, source.getSourceId(), game, tapped); if (!game.isSimulation()) { game.informPlayers( controller.getLogName() + " moves " + card.getLogName() + " to " + zone.toString().toLowerCase()); } } } } game.getExile().getExileZone(exileId).clear(); } return true; } return false; }
@Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); Card card = game.getCard(this.cardId); if (controller != null && card != null) { controller.moveCardToExileWithInfo( card, null, "", source.getSourceId(), game, Zone.STACK, true); return true; } return false; }
@Override public boolean canTarget(UUID id, Ability source, Game game) { Card card = game.getCard(id); if (card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD) { UUID firstTarget = source.getFirstTarget(); if (firstTarget != null && game.getPlayer(firstTarget).getGraveyard().contains(id)) { return filter.match(card, game); } } return false; }
@Override public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source)); if (targetPlayer != null) { ArrayList<UUID> graveyard = new ArrayList<UUID>(targetPlayer.getGraveyard()); for (UUID cardId : graveyard) { game.getCard(cardId).moveToZone(Zone.EXILED, cardId, game, false); } return true; } return false; }
@Override public UUID getFirst(Game game, Ability source) { // check target not changed zone if (this.zoneChangeCounter > 0) { // will be zero if not defined in init Card card = game.getCard(target); if (card != null && card.getZoneChangeCounter(game) != this.zoneChangeCounter) { return null; } } return target; }
@Override public boolean apply(Game game, Ability source) { CardsImpl cardsInExile = new CardsImpl(); TargetCard target = new TargetCard(Zone.EXILED, new FilterCreatureCard()); Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { ExileZone exile = game.getExile().getExileZone(exileId); if (exile != null) { LinkedList<UUID> cards = new LinkedList<>(exile); for (UUID cardId : cards) { Card card = game.getCard(cardId); cardsInExile.add(card); } if (controller.choose(Outcome.PutCreatureInPlay, cardsInExile, target, game)) { Card chosenCard = game.getCard(target.getFirstTarget()); return controller.moveCards(chosenCard, Zone.BATTLEFIELD, source, game); } } } return false; }
@Override public boolean apply(Game game, Ability source) { Card card = game.getCard(targetPointer.getFirst(game, source)); if (card != null) { Player player = game.getPlayer(card.getOwnerId()); if (player != null) { if (player.getGraveyard().size() == 0) { return new FlipSourceEffect(new NighteyesTheDesecratorToken()).apply(game, source); } } } return false; }
@Override public int calculate(Game game, Ability source, Effect effect) { int count = 0; Card card = game.getCard(source.getSourceId()); if (card != null) { for (Ability ability : card.getAbilities()) { if (ability instanceof KickerAbility) { count += ((KickerAbility) ability).getXManaValue(); } } } return count; }