@Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.DAMAGE_PLAYER) { DamageEvent damageEvent = (DamageEvent) event; UUID playerId = getSourceControllerId(event.getSourceId(), game); if (!damageEvent.isCombatDamage() && game.getOpponents(event.getTargetId()).contains(playerId)) { Player target = game.getPlayer(event.getTargetId()); Player player = game.getPlayer(playerId); if (target != null && player != null) { int numPlaneswalkers = game.getBattlefield().countAll(filter, target.getId(), game); if (numPlaneswalkers > 0 && player.chooseUse(outcome, "Redirect damage to planeswalker?", game)) { redirectTarget = new TargetPermanent(filter); if (numPlaneswalkers == 1) { redirectTarget.add( game.getBattlefield() .getAllActivePermanents(filter, target.getId(), game) .get(0) .getId(), game); } else { player.choose(Outcome.Damage, redirectTarget, null, game); } return true; } } } } return false; }
@Override public boolean apply(Game game, Ability source) { Permanent sourcePermanent = (Permanent) game.getLastKnownInformation( targetPointer.getFirst(game, source), Constants.Zone.BATTLEFIELD); if (sourcePermanent == null) { return false; } Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; } Cards revealed = new CardsImpl(); Card artifactCard = null; Cards nonArtifactCards = new CardsImpl(); Player player = game.getPlayer(sourcePermanent.getControllerId()); while (artifactCard == null && player.getLibrary().size() > 0) { Card card = player.getLibrary().removeFromTop(game); revealed.add(card); if (card.getCardType().contains(CardType.ARTIFACT)) artifactCard = card; else nonArtifactCards.add(card); } player.revealCards("Shape Anew", revealed, game); if (artifactCard != null) { artifactCard.putOntoBattlefield( game, Constants.Zone.LIBRARY, source.getId(), player.getId()); } player.getLibrary().addAll(nonArtifactCards.getCards(game), game); player.shuffleLibrary(game); return true; }
@Override public boolean canPay(UUID sourceId, UUID controllerId, Game game) { if (!game.getPlayer(controllerId).isLifeTotalCanChange()) { return false; } return game.getPlayer(controllerId).getLife() >= 2; }
@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; }
protected void calculatePostCombatActions(Game game) { if (!getNextAction(game)) { currentScore = GameStateEvaluator2.evaluate(playerId, game); Game sim = createSimulation(game); SimulationNode2.resetCount(); root = new SimulationNode2(null, sim, maxDepth, playerId); logger.debug( "Sim Calculate post combat actions ----------------------------------------------------------------------------------------"); addActionsTimed(); if (root != null && root.children.size() > 0) { root = root.children.get(0); int bestScore = root.getScore(); if (bestScore > currentScore || allowBadMoves) { actions = new LinkedList<>(root.abilities); combat = root.combat; } else { logger.debug( "[" + game.getPlayer(playerId).getName() + "] no better score current: " + currentScore + " bestScore: " + bestScore); } } else { logger.debug("[" + game.getPlayer(playerId).getName() + "][post] Action: skip"); } } }
@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) { 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) { int maxDiscarded = 0; Player sourcePlayer = game.getPlayer(source.getControllerId()); if (sourcePlayer == null) { return false; } for (UUID playerId : sourcePlayer.getInRange()) { 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 : sourcePlayer.getInRange()) { Player player = game.getPlayer(playerId); if (player != null) { player.drawCards(maxDiscarded, game); } } return true; }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { boolean lessCreatures = false; boolean lessLife = false; FilterPermanent filter = new FilterCreaturePermanent(); int count = game.getBattlefield().countAll(filter, controller.getId(), game); for (UUID uuid : game.getOpponents(controller.getId())) { Player opponent = game.getPlayer(uuid); if (opponent != null) { if (opponent.getLife() > controller.getLife()) { lessLife = true; } if (game.getBattlefield().countAll(filter, uuid, game) > count) { lessCreatures = true; } } if (lessLife && lessCreatures) { // no need to search further break; } } if (lessLife) { controller.gainLife(6, game); } if (lessCreatures) { Effect effect = new CreateTokenEffect(new SoldierToken(), 3); effect.apply(game, source); } return true; } return false; }
/** * Checks if there are enough {@link Permanent} or {@link Player} that can be chosen. Should only * be used for Ability targets since this checks for protection, shroud etc. * * @param sourceId - the target event source * @param sourceControllerId - controller of the target event source * @param game * @return - true if enough valid {@link Permanent} or {@link Player} exist */ @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { int count = 0; MageObject targetSource = game.getObject(sourceId); for (UUID playerId : game.getPlayer(sourceControllerId).getInRange()) { Player player = game.getPlayer(playerId); if (player != null && player.canBeTargetedBy(targetSource, game) && filter.match(player, game)) { count++; if (count >= this.minNumberOfTargets) { return true; } } } for (Permanent permanent : game.getBattlefield() .getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) { count++; if (count >= this.minNumberOfTargets) { return true; } } } return false; }
@Override public boolean apply(Game game, Ability source) { Player player1 = game.getPlayer(source.getFirstTarget()); Player player2 = game.getPlayer(source.getTargets().get(1).getFirstTarget()); if (player1 != null && player2 != null) { int lifePlayer1 = player1.getLife(); int lifePlayer2 = player2.getLife(); if (lifePlayer1 == lifePlayer2) return false; if (!player1.isLifeTotalCanChange() || !player2.isLifeTotalCanChange()) return false; // 20110930 - 118.7, 118.8 if (lifePlayer1 < lifePlayer2 && (!player1.isCanGainLife() || !player2.isCanLoseLife())) return false; if (lifePlayer1 > lifePlayer2 && (!player1.isCanLoseLife() || !player2.isCanGainLife())) return false; player1.setLife(lifePlayer2, game); player2.setLife(lifePlayer1, game); return true; } return false; }
@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 controller = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayer(source.getFirstTarget()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (controller != null && opponent != null && sourcePermanent != null) { opponent.revealCards(sourcePermanent.getName(), opponent.getHand(), game); TargetCard target = new TargetCard(Zone.PICK, new FilterNonlandCard("nonland card to exile")); if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { Card card = opponent.getHand().get(target.getFirstTarget(), game); if (card != null) { controller.moveCardToExileWithInfo( card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND); } } return true; } return false; }
protected void simulateOptions(Game game, Ability previousActions) { allActions.add(previousActions); List<Ability> playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer); for (Ability ability : playables) { List<Ability> options = game.getPlayer(playerId).getPlayableOptions(ability, game); if (options.isEmpty()) { if (ability.getManaCosts().getVariableCosts().size() > 0) { simulateVariableCosts(ability, game); } else { allActions.add(ability); } // simulateAction(game, previousActions, ability); } else { // ExecutorService simulationExecutor = Executors.newFixedThreadPool(4); for (Ability option : options) { if (ability.getManaCosts().getVariableCosts().size() > 0) { simulateVariableCosts(option, game); } else { allActions.add(option); } // SimulationWorker worker = new SimulationWorker(game, this, // previousActions, option); // simulationExecutor.submit(worker); } // simulationExecutor.shutdown(); // while(!simulationExecutor.isTerminated()) {} } } }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source)); if (controller != null && targetPlayer != null) { game.getState().getTurnMods().add(new TurnMod(targetPlayer.getId(), false)); } return super.apply(game, source); }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(targetPointer.getFirst(game, source)); if (player != null && controller != null) { controller.lookAtCards("Walker of Secret Ways", player.getHand(), game); } 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) { Cards cardsToCast = new CardsImpl(); Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source)); MageObject sourceObject = source.getSourceObject(game); if (targetOpponent != null && sourceObject != null) { List<Card> allCards = targetOpponent.getLibrary().getTopCards(game, 7); Cards cards = new CardsImpl(Zone.LIBRARY, allCards); targetOpponent.revealCards( sourceObject.getIdName() + " - " + targetOpponent.getName() + "'s top library cards", cards, game); for (Card card : allCards) { if (filter.match(card, game)) { cardsToCast.add(card); } } // cast an instant or sorcery for free if (cardsToCast.size() > 0) { int numberOfSpells = 1; if (SpellMasteryCondition.getInstance().apply(game, source)) { numberOfSpells++; } Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { TargetCard target = new TargetCard(Zone.LIBRARY, filter); // zone should be ignored here target.setNotTarget(true); while (numberOfSpells > 0 && cardsToCast.size() > 0 && controller.chooseUse( outcome, "Cast an instant or sorcery card from among them for free?", source, game) && controller.choose(outcome, cardsToCast, target, game)) { Card card = cardsToCast.get(target.getFirstTarget(), game); if (card != null) { controller.cast(card.getSpellAbility(), game, true); numberOfSpells--; cardsToCast.remove(card); allCards.remove(card); } if (!controller.isInGame()) { return false; } target.clearChosen(); } } targetOpponent.moveCards(allCards, Zone.LIBRARY, Zone.GRAVEYARD, source, game); } return true; } return false; }
@Override public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(source.getFirstTarget()); Player controllerPlayer = game.getPlayer(source.getControllerId()); if (targetPlayer != null && controllerPlayer != null) { targetPlayer.damage(1, source.getSourceId(), game, false, true); controllerPlayer.gainLife(1, game); } return false; }
@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; }
@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 Set<UUID> possibleTargets(UUID sourceControllerId, Game game) { Set<UUID> possibleTargets = new HashSet<UUID>(); for (UUID playerId : game.getPlayer(sourceControllerId).getInRange()) { Player player = game.getPlayer(playerId); if (player != null && !player.hasLeft() && filter.match(player, game)) { possibleTargets.add(playerId); } } return possibleTargets; }
/** * Checks if there are enough {@link Player} that can be selected. Should not be used for Ability * targets since this does not check for protection, shroud etc. * * @param sourceControllerId - controller of the select event * @param game * @return - true if enough valid {@link Player} exist */ @Override public boolean canChoose(UUID sourceControllerId, Game game) { int count = 0; for (UUID playerId : game.getPlayer(sourceControllerId).getInRange()) { Player player = game.getPlayer(playerId); if (player != null && !player.hasLeft() && filter.match(player, game)) { count++; if (count >= this.minNumberOfTargets) return true; } } return false; }
@Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayer(source.getFirstTarget()); if (opponent != null || player != null && opponent.getHand().size() > player.getHand().size()) { player.drawCards(opponent.getHand().size() - player.getHand().size(), game); return true; } return false; }
@Override public boolean apply(Game game, Ability source) { int damageDealt = 0; for (UUID playerId : game.getPlayerList()) { if (!playerId.equals(source.getControllerId())) { damageDealt += game.getPlayer(playerId).damage(2, source.getSourceId(), game, false, true); } } if (damageDealt > 0) { game.getPlayer(source.getControllerId()).gainLife(damageDealt, game); } return true; }
@Override public boolean apply(Game game, Ability source) { Player opponent = game.getPlayer(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); if (opponent != null && controller != null) { int amount = controller.getHand().size() - opponent.getHand().size(); if (amount > 0) { opponent.damage(amount, source.getSourceId(), game, false, true); return true; } } return false; }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player newController = game.getPlayer(this.getTargetPointer().getFirst(game, source)); if (newController != null && controller != null && !controller.equals(newController)) { ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, newController.getId()); effect.setTargetPointer(new FixedTarget(source.getSourceId())); game.addEffect(effect, source); return true; } return false; }
@Override public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set<UUID> possibleTargets = new HashSet<UUID>(); MageObject targetSource = game.getObject(sourceId); for (UUID playerId : game.getPlayer(sourceControllerId).getInRange()) { Player player = game.getPlayer(playerId); if (player != null && !player.hasLeft() && filter.match(player, sourceId, sourceControllerId, game)) { if (player.canBeTargetedBy(targetSource, game)) possibleTargets.add(playerId); } } return possibleTargets; }
@Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { int cardsInHand = player.getHand().size(); for (UUID playerId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(playerId); if (opponent != null && opponent.getHand().size() >= cardsInHand) { return false; } } } return true; }
@Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { Card card = game.getCard(source.getSourceId()); if (card != null) { Player owner = game.getPlayer(card.getOwnerId()); if (owner != null && owner.getGraveyard().contains(card.getId())) { controller.moveCards(card, Zone.BATTLEFIELD, source, game, false, true, false, null); } } return true; } return false; }