@Override public void setGameUnderYourControl(boolean value, boolean fullRestore) { this.isGameUnderControl = value; if (isGameUnderControl) { if (fullRestore) { this.turnControllers.clear(); this.turnController = getId(); } else { if (turnControllers.size() > 0) { this.turnControllers.remove(turnControllers.size() - 1); } if (turnControllers.isEmpty()) { this.turnController = getId(); } else { this.turnController = turnControllers.get(turnControllers.size() - 1); isGameUnderControl = false; } } } }
@Override public boolean hasOpponent(UUID playerToCheckId, Game game) { return !this.getId().equals(playerToCheckId) && game.isOpponent(this, playerToCheckId) && getInRange().contains(playerToCheckId); }
@Override public void controlPlayersTurn(Game game, UUID playerId) { Player player = game.getPlayer(playerId); player.setTurnControlledBy(this.getId()); game.informPlayers(getLogName() + " controls the turn of " + player.getLogName()); if (!playerId.equals(this.getId())) { this.playersUnderYourControl.add(playerId); if (!player.hasLeft() && !player.hasLost()) { player.setGameUnderYourControl(false); } DelayedTriggeredAbility ability = new AtTheEndOfTurnStepPostDelayedTriggeredAbility(new LoseControlOnOtherPlayersControllerEffect(this.getLogName(), player.getLogName())); ability.setSourceId(getId()); ability.setControllerId(getId()); game.addDelayedTriggeredAbility(ability); } }
if (card.isOwnedBy(getId())) { sb.append(" of their library"); } else {
@Override public boolean moveCardToGraveyardWithInfo(Card card, UUID sourceId, Game game, Zone fromZone ) { if (card == null) { return false; } boolean result = false; // Zone fromZone = game.getState().getZone(card.getId()); if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null && fromZone == Zone.BATTLEFIELD)) { if (!game.isSimulation()) { if (card instanceof PermanentCard && game.getCard(card.getId()) != null) { card = game.getCard(card.getId()); } StringBuilder sb = new StringBuilder(this.getLogName()) .append(" puts ").append(card.getLogName()).append(' ').append(card.isCopy() ? "(Copy) " : "") .append(fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + ' ' : ""); if (card.isOwnedBy(getId())) { sb.append("into their graveyard"); } else { sb.append("it into its owner's graveyard"); } game.informPlayers(sb.toString()); } result = true; } return result; }
@Override public boolean lookAtFaceDownCard(Card card, Game game ) { if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.LOOK_AT_FACE_DOWN, card.getSpellAbility(), this.getId(), game)) { if (chooseUse(Outcome.Benefit, "Look at that card?", null, game)) { Cards cards = new CardsImpl(card); this.lookAtCards(getName() + " - " + sdf.format(System.currentTimeMillis()), cards, game); return true; } } return false; }
@Override public void removeCounters(String name, int amount, Ability source, Game game) { for (int i = 0; i < amount; i++) { if (!counters.removeCounter(name, 1)) { break; } GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTER_REMOVED, getId(), (source == null ? null : source.getSourceId()), (source == null ? null : source.getControllerId())); event.setData(name); event.setAmount(1); game.fireEvent(event); } }
@Override public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) { if (this.hasLost() || this.hasLeft()) { return false; } if (source != null) { if (abilities.containsKey(ShroudAbility.getInstance().getId())) { return false; } if (abilities.containsKey(HexproofAbility.getInstance().getId())) { if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game) && null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, this.getId(), game)) { return false; } } return !hasProtectionFrom(source, game); } return true; }
this.turnController = this.getId(); this.turnControllers.clear(); this.playersUnderYourControl.clear();
private void getPlayableFromGraveyardCard(Game game, Card card, Abilities<Ability> candidateAbilities, ManaOptions availableMana, List<Ability> output) { MageObjectReference permittingObject = game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, card.getSpellAbility(), this.getId(), game); for (ActivatedAbility ability : candidateAbilities.getActivatedAbilities(Zone.ALL)) { boolean possible = false; if (ability.getZone().match(Zone.GRAVEYARD)) { possible = true; } else if (ability.getZone().match(Zone.HAND) && (ability instanceof SpellAbility || ability instanceof PlayLandAbility)) { if (permittingObject != null || canPlayCardsFromGraveyard()) { possible = true; } } if (possible && canPlay(ability, availableMana, card, game)) { output.add(ability); } } }
@Override public void lookAtAllLibraries(Ability source, Game game) { for (UUID playerId : game.getState().getPlayersInRange(this.getId(), game)) { Player player = game.getPlayer(playerId); String playerName = this.getName().equals(player.getName()) ? "Your " : player.getName() + "'s "; playerName += "library"; Cards cardsInLibrary = new CardsImpl(player.getLibrary().getTopCards(game, player.getLibrary().size())); lookAtCards(playerName, cardsInLibrary, game); } }
if (!Objects.equals(ownerId, this.getId())) { choosingPlayer = game.getPlayer(ownerId);
@Override public boolean surveil(int value, Ability source, Game game) { GameEvent event = new GameEvent(GameEvent.EventType.SURVEIL, getId(), source == null ? null : source.getSourceId(), getId(), value, true); if (game.replaceEvent(event)) { return false; } game.informPlayers(getLogName() + " surveils " + event.getAmount()); Cards cards = new CardsImpl(); cards.addAll(getLibrary().getTopCards(game, event.getAmount())); if (!cards.isEmpty()) { String text; if (cards.size() == 1) { text = "card if you want to put it into your graveyard (Surveil)"; } else { text = "cards you want to put into your graveyard (Surveil)"; } TargetCard target = new TargetCard(0, cards.size(), Zone.LIBRARY, new FilterCard(text)); chooseTarget(Outcome.Benefit, cards, target, source, game); moveCards(new CardsImpl(target.getTargets()), Zone.GRAVEYARD, source, game); cards.removeAll(target.getTargets()); putCardsOnTopOfLibrary(cards, game, source, true); } game.fireEvent(new GameEvent(GameEvent.EventType.SURVEILED, getId(), source == null ? null : source.getSourceId(), getId(), event.getAmount(), true)); return true; }
@Override public void phasing(Game game) { //20091005 - 502.1 List<Permanent> phasedOut = game.getBattlefield().getPhasedOut(playerId); for (Permanent permanent : game.getBattlefield().getPhasedIn(playerId)) { // 502.15i When a permanent phases out, any local enchantments or Equipment // attached to that permanent phase out at the same time. This alternate way of // phasing out is known as phasing out "indirectly." An enchantment or Equipment // that phased out indirectly won't phase in by itself, but instead phases in // along with the card it's attached to. Permanent attachedTo = game.getPermanent(permanent.getAttachedTo()); if (!(attachedTo != null && attachedTo.isControlledBy(this.getId()))) { permanent.phaseOut(game, false); } } for (Permanent permanent : phasedOut) { if (!permanent.isPhasedOutIndirectly()) { permanent.phaseIn(game); } } }
if (card.isLand() && ability instanceof AlternativeSourceCosts) { if (canLandPlayAlternateSourceCostsAbility(card, available, ability, game)) { // e.g. Land with Morph if (game.canPlaySorcery(getId())) { playable.add(card.getId());
@Override public boolean scry(int value, Ability source, Game game) { game.informPlayers(getLogName() + " scries " + value); Cards cards = new CardsImpl(); cards.addAll(getLibrary().getTopCards(game, value)); if (!cards.isEmpty()) { String text; if (cards.size() == 1) { text = "card if you want to put it on the bottom of your library (Scry)"; } else { text = "cards you want to put on the bottom of your library (Scry)"; } TargetCard target = new TargetCard(0, cards.size(), Zone.LIBRARY, new FilterCard(text)); chooseTarget(Outcome.Benefit, cards, target, source, game); putCardsOnBottomOfLibrary(new CardsImpl(target.getTargets()), game, source, true); cards.removeAll(target.getTargets()); putCardsOnTopOfLibrary(cards, game, source, true); } game.fireEvent(new GameEvent(GameEvent.EventType.SCRY, getId(), source == null ? null : source.getSourceId(), getId(), value, true)); return true; }
@Override public boolean moveCardToHandWithInfo(Card card, UUID sourceId, Game game, boolean withName ) { boolean result = false; Zone fromZone = game.getState().getZone(card.getId()); if (fromZone == Zone.BATTLEFIELD && !(card instanceof Permanent)) { card = game.getPermanent(card.getId()); } if (card.moveToZone(Zone.HAND, sourceId, game, false)) { if (card instanceof PermanentCard && game.getCard(card.getId()) != null) { card = game.getCard(card.getId()); } if (!game.isSimulation()) { game.informPlayers(getLogName() + " puts " + (withName ? card.getLogName() : (card.isFaceDown(game) ? "a face down card" : "a card")) + " from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + ' ' + (card.isOwnedBy(this.getId()) ? "into their hand" : "into its owner's hand") ); } result = true; } return result; }
if (ability.getCosts().canPay(ability, sourceObject.getId(), this.getId(), game)) { ManaCostsImpl manaCosts = new ManaCostsImpl(); for (Cost cost : ability.getCosts()) {
@Override public boolean putCardOnTopXOfLibrary(Card card, Game game, Ability source, int xFromTheTop) { if (card.isOwnedBy(getId())) { if (library.size() + 1 < xFromTheTop) { putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, true); } else { if (card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true) && !(card instanceof PermanentToken) && !card.isCopy()) { card = getLibrary().removeFromTop(game); getLibrary().putCardToTopXPos(card, xFromTheTop, game); game.informPlayers(card.getLogName() + " is put into " + getLogName() + "'s library " + CardUtil.numberToOrdinalText(xFromTheTop) + " from the top"); } else { return false; } } } else { return game.getPlayer(card.getOwnerId()).putCardOnTopXOfLibrary(card, game, source, xFromTheTop); } return true; }