@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { int xSum = 0; xSum += playerPaysXGenericMana(controller, source, game); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { if (playerId != controller.getId()) { Player player = game.getPlayer(playerId); if (player != null) { xSum += playerPaysXGenericMana(player, source, game); } } } if (xSum > 0) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Effect effect = new PutTopCardOfLibraryIntoGraveTargetEffect(xSum); effect.setTargetPointer(new FixedTarget(playerId)); effect.apply(game, source); } } // prevent undo controller.resetStoredBookmark(game); return true; } return false; }
@Override public boolean apply(Game game, Ability source) { Player you = game.getPlayer(source.getControllerId()); if (you != null) { Spell spell = game.getStack().getSpell(this.getTargetPointer().getFirst(game, source)); if (spell != null) { ObjectColor color1 = new ObjectColor((String) game.getState().getValue(source.getSourceId() + "_color1")); ObjectColor color2 = new ObjectColor((String) game.getState().getValue(source.getSourceId() + "_color2")); int amount = 0; if (spell.getColor(game).contains(color1)) { ++amount; } if (spell.getColor(game).contains(color2)) { ++amount; } if (amount > 0) { you.gainLife(amount, game); return true; } } } return false; }
@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 boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (player != null && permanent != null) { String colors; ChoiceColor colorChoice = new ChoiceColor(); colorChoice.setMessage("Choose the first color"); while (!player.choose(Outcome.GainLife, colorChoice, game)) { if (!player.canRespond()) { return false; } } game.getState().setValue(permanent.getId() + "_color1", colorChoice.getColor().toString()); colors = colorChoice.getChoice().toLowerCase() + " and "; colorChoice.getChoices().remove(colorChoice.getChoice()); colorChoice.setMessage("Choose the second color"); while (!player.choose(Outcome.GainLife, colorChoice, game) && player.canRespond()) { game.debugMessage("player canceled choosing type. retrying."); } game.getState().setValue(permanent.getId() + "_color2", colorChoice.getColor().toString()); colors = colors + colorChoice.getChoice().toLowerCase(); game.informPlayers( permanent.getName() + ": " + player.getLogName() + " has chosen " + colors); } return false; }
@Override public boolean apply(Game game, Ability source) { int maxDiscarded = 0; Player sourcePlayer = game.getPlayer(source.getControllerId()); if (sourcePlayer == null) { return false; } for (UUID playerId : game.getState().getPlayersInRange(sourcePlayer.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { int discarded = 0; for (Card c : player.getHand().getCards(game)) { if (player.discard(c, source, game)) { discarded++; } } if (discarded > maxDiscarded) { maxDiscarded = discarded; } } } for (UUID playerId : game.getState().getPlayersInRange(sourcePlayer.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { player.drawCards(maxDiscarded, game); } } return true; }
@Override public void trigger(Game game, UUID controllerId) { // 20100716 - 603.8 Boolean triggered = (Boolean) game.getState().getValue(this.id.toString() + "triggered"); if (triggered == null) triggered = Boolean.FALSE; if (!triggered) { game.getState().setValue(this.id.toString() + "triggered", Boolean.TRUE); super.trigger(game, controllerId); } }
public static ActivationInfo getInstance(Game game, UUID sourceId, int zoneChangeCounter) { String key = "ActivationInfo" + sourceId.toString() + zoneChangeCounter; Integer activations = (Integer) game.getState().getValue(key); ActivationInfo activationInfo; if (activations != null) { Integer turnNum = (Integer) game.getState().getValue(key + "T"); activationInfo = new ActivationInfo(game, turnNum, activations); } else { activationInfo = new ActivationInfo(game, game.getTurnNum(), 0); } activationInfo.setKey(key); return activationInfo; }
@Override public boolean resolve(Game game) { boolean result = true; // 20100716 - 117.12 if (checkIfClause(game)) { for (Effect effect : getEffects()) { if (effect instanceof OneShotEffect) { boolean effectResult = effect.apply(game, this); result &= effectResult; if (logger.isDebugEnabled()) { if (!this.getAbilityType().equals(AbilityType.MANA)) { if (!effectResult) { if (this.getSourceId() != null) { MageObject mageObject = game.getObject(this.getSourceId()); if (mageObject != null) { logger.debug("AbilityImpl.resolve: object: " + mageObject.getName()); } } logger.debug( "AbilityImpl.resolve: effect returned false -" + effect.getText(this.getModes().getMode())); } } } } else { game.addEffect((ContinuousEffect) effect, this); } /** * All restrained trigger events are fired now. To restrain the events is mainly neccessary * because of the movement of multiple object at once. If the event is fired directly as one * object moved, other objects are not already in the correct zone to check for their * effects. (e.g. Valakut, the Molten Pinnacle) */ game.getState().handleSimultaneousEvent(game); game.resetShortLivingLKI(); /** * game.applyEffects() has to be done at least for every effect that moves cards/permanent * between zones, or changes control of objects so Static effects work as intened if * dependant from the moved objects zone it is in Otherwise for example were static * abilities with replacement effects deactivated too late Example: {@link * org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy} */ if (effect.applyEffectsAfter()) { game.applyEffects(); game.getState().getTriggers().checkStateTriggers(game); } } } return result; }
@Override public boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event) { MageObject object = source; // for singleton abilities like Flying we can't rely on abilities' source because it's only once // in continuous effects // so will use the sourceId of the object itself that came as a parameter if it is not null if (object == null) { object = game.getPermanentEntering(getSourceId()); if (object == null) { object = game.getObject(getSourceId()); } } if (object != null) { if (object instanceof Permanent) { if (!((Permanent) object).getAbilities(game).contains(this)) { return false; } return ((Permanent) object).isPhasedIn(); } else if (!object.getAbilities().contains(this)) { // check if it's an ability that is temporary gained to a card Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(this.getSourceId()); if (otherAbilities == null || !otherAbilities.contains(this)) { return false; } } } return true; }
/** * @param game * @param source * @return */ @Override public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { if (!this.hasSourceObjectAbility(game, source, event)) { return false; } if (zone.equals(Zone.COMMAND)) { if (this.getSourceId() == null) { // commander effects return true; } MageObject object = game.getObject(this.getSourceId()); // emblem are always actual if (object != null && object instanceof Emblem) { return true; } } UUID parameterSourceId; // for singleton abilities like Flying we can't rely on abilities' source because it's only once // in continuous effects // so will use the sourceId of the object itself that came as a parameter if it is not null if (this instanceof MageSingleton && source != null) { parameterSourceId = source.getId(); } else { parameterSourceId = getSourceId(); } // check agains shortLKI for effects that move multiple object at the same time (e.g. destroy // all) if (game.getShortLivingLKI(getSourceId(), getZone())) { return true; } // check against current state Zone test = game.getState().getZone(parameterSourceId); return test != null && zone.match(test); }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; } int totalPowerSacrificed = 0; List<UUID> perms = new ArrayList<>(); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent( 1, 1, new FilterControlledCreaturePermanent(), true); if (target.canChoose(player.getId(), game)) { while (!target.isChosen() && player.canRespond()) { player.choose(Outcome.Sacrifice, target, source.getSourceId(), game); } perms.addAll(target.getTargets()); } } } for (UUID permID : perms) { Permanent permanent = game.getPermanent(permID); if (permanent != null) { int power = permanent.getPower().getValue(); if (permanent.sacrifice(source.getSourceId(), game)) { totalPowerSacrificed += power; } } } new CreateTokenEffect(new ReignOfThePitToken(totalPowerSacrificed)).apply(game, source); return true; }
@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) { Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); Permanent sourceObject = game.getPermanent(source.getSourceId()); if (permanent != null && sourceObject != null) { PutTokenOntoBattlefieldCopyTargetEffect effect = new PutTokenOntoBattlefieldCopyTargetEffect(); effect.setTargetPointer(new FixedTarget(permanent, game)); effect.apply(game, source); game.getState().setValue(source.getSourceId() + "_token", effect.getAddedPermanent()); for (Permanent addedToken : effect.getAddedPermanent()) { Effect sacrificeEffect = new SacrificeTargetEffect("sacrifice Dance of Many"); sacrificeEffect.setTargetPointer(new FixedTarget(sourceObject, game)); LeavesBattlefieldTriggeredAbility triggerAbility = new LeavesBattlefieldTriggeredAbility(sacrificeEffect, false); ContinuousEffect continuousEffect = new GainAbilityTargetEffect(triggerAbility, Duration.WhileOnBattlefield); continuousEffect.setTargetPointer(new FixedTarget(addedToken, game)); game.addEffect(continuousEffect, 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 you = game.getPlayer(source.getControllerId()); if (you != null) { ChoiceImpl choices = new ChoiceImpl(true); choices.setMessage("Choose basic land type"); choices.isRequired(); choices.getChoices().add("Forest"); choices.getChoices().add("Plains"); choices.getChoices().add("Mountain"); choices.getChoices().add("Island"); choices.getChoices().add("Swamp"); if (you.choose(Outcome.Neutral, choices, game)) { game.informPlayers( new StringBuilder("Realmwright: ") .append(" Chosen basic land type is ") .append(choices.getChoice()) .toString()); game.getState() .setValue(source.getSourceId().toString() + "_Realmwright", choices.getChoice()); return true; } } return false; }
@Override public boolean apply(Game game, Ability source) { Permanent triggeringCreature = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (triggeringCreature != null) { Permanent sourceCreature = game.getPermanent(source.getSourceId()); if (sourceCreature != null && EvolveAbility.isPowerOrThoughnessGreater(sourceCreature, triggeringCreature)) { game.getState().setValue("EvolveAddCounterActive", Boolean.TRUE); sourceCreature.addCounters(CounterType.P1P1.createInstance(), game); game.getState().setValue("EvolveAddCounterActive", Boolean.FALSE); } return true; } return false; }
@Override public boolean apply(Game game, Ability source) { BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get("DamagedOpponents", source.getControllerId()); return !watcher.conditionMet(); }
@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) { DamageDoneWatcher watcher = (DamageDoneWatcher) game.getState().getWatchers().get("DamageDone"); return watcher != null && watcher.damageDone(source.getSourceId(), source.getSourceObjectZoneChangeCounter(), game) >= value; }
@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 resolve(Game game) { boolean value = super.resolve(game); if (value == true) { game.getState().setValue(this.originalId.toString() + "addMana", Boolean.TRUE); } return value; }
@Override public boolean apply(Game game, Ability source) { FaithsRewardWatcher watcher = (FaithsRewardWatcher) game.getState().getWatchers().get("FaithsRewardWatcher"); if (watcher != null) { for (UUID id : watcher.cards) { Card c = game.getCard(id); if (c != null && c.getOwnerId().equals(source.getControllerId()) && game.getState().getZone(id) == Constants.Zone.GRAVEYARD) { c.moveToZone(Constants.Zone.BATTLEFIELD, source.getSourceId(), game, false); } } return true; } return false; }
@Override public void adjustCosts(Ability ability, Game game) { Player player = game.getPlayer(ability.getFirstTarget()); if (player != null) { String key = CardUtil.getCardZoneString("targetPlayer", this.getSourceId(), game); game.getState().setValue(key, player.getId()); } }
private void saveAttackingCreature(UUID attackerId, Integer zoneChangeCounter, Game game) { Set<String> attackers; Map<Integer, Set<String>> attackerMap; Object object = game.getState().getValue("blockedAttackers" + getSourceId()); if (object != null && object instanceof Map) { attackerMap = (Map<Integer, Set<String>>) object; } else { attackerMap = new HashMap<>(); } attackers = attackerMap.get(zoneChangeCounter); if (attackers == null) { attackers = new HashSet<>(); attackerMap.put(zoneChangeCounter, attackers); } attackers.add(CardUtil.getCardZoneString(null, attackerId, game)); game.getState().setValue("blockedAttackers" + getSourceId().toString(), attackerMap); }
@Override public boolean hasAbility(UUID abilityId, Game game) { if (this.getAbilities().containsKey(abilityId)) { return true; } Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(getId()); return otherAbilities != null && otherAbilities.containsKey(abilityId); }
Cards ProteanHulkSearch(Game game, Ability source) { Cards cardsPicked = new CardsImpl(Zone.PICK); Player player = game.getPlayer(source.getControllerId()); if (player != null) { GameEvent event = GameEvent.getEvent( GameEvent.EventType.SEARCH_LIBRARY, source.getControllerId(), source.getControllerId(), source.getControllerId(), Integer.MAX_VALUE); if (!game.replaceEvent(event)) { int manaCostLeftToFetch = 6; int librarySearchLimit = event.getAmount(); FilterCard filter = new FilterCreatureCard( "number of creature cards with total converted mana cost 6 or less (6 CMC left)"); filter.add( new ConvertedManaCostPredicate(ComparisonType.LessThan, manaCostLeftToFetch + 1)); TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter); target.setCardLimit(librarySearchLimit); while (target.canChoose(source.getSourceId(), source.getControllerId(), game)) { target.choose( Outcome.PutCreatureInPlay, source.getControllerId(), source.getControllerId(), game); Card card = player.getLibrary().remove(target.getFirstTarget(), game); if (card == null) { break; } cardsPicked.add(card); game.setZone(card.getId(), Zone.PICK); game.getState().getLookedAt(source.getControllerId()).add("Protean Hulk", cardsPicked); librarySearchLimit--; if (librarySearchLimit == 0) { break; } manaCostLeftToFetch -= card.getManaCost().convertedManaCost(); filter = new FilterCreatureCard( "number of creature cards with total converted mana cost 6 or less (" + manaCostLeftToFetch + " CMC left)"); filter.add( new ConvertedManaCostPredicate(ComparisonType.LessThan, manaCostLeftToFetch + 1)); target = new TargetCardInLibrary(0, 1, filter); target.setCardLimit(librarySearchLimit); } game.fireEvent( GameEvent.getEvent( GameEvent.EventType.LIBRARY_SEARCHED, source.getControllerId(), source.getControllerId())); } } return cardsPicked; }
@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; }
@Override public boolean apply(Game game, Ability source) { UUID playerId = (UUID) game.getState().getValue(source.getSourceId() + "_player"); Player player = game.getPlayer(playerId); if (player != null && player.isInGame()) { player.damage((Integer) this.getValue("damageAmount"), source.getId(), game, false, true); } return true; }
@Override public void postResolve(Card card, Ability source, UUID controllerId, Game game) { Card revealed = (Card) game.getState().getValue(source.getId().toString()); if (revealed != null && revealed.getCardType().contains(CardType.LAND)) { card.moveToZone(Zone.HAND, source.getId(), game, false); } else { card.moveToZone(Zone.GRAVEYARD, source.getId(), game, false); } }
@Override public void setSourceObject(MageObject sourceObject, Game game) { if (sourceObject == null) { this.sourceObject = game.getObject(sourceId); } else { this.sourceObject = sourceObject; } this.sourceObjectZoneChangeCounter = game.getState().getZoneChangeCounter(sourceId); }