public void removeCopiedCard(Card card) { if (copiedCards.containsKey(card.getId())) { copiedCards.remove(card.getId()); cardState.remove(card.getId()); zones.remove(card.getId()); zoneChangeCounter.remove(card.getId()); } // TODO Watchers? // TODO Abilities? if (card.isSplitCard()) { removeCopiedCard(((SplitCard) card).getLeftHalfCard()); removeCopiedCard(((SplitCard) card).getRightHalfCard()); } }
public Spell(Card card, SpellAbility ability, UUID controllerId, Zone fromZone) { this.card = card; this.color = card.getColor(null).copy(); this.frameColor = card.getFrameColor(null).copy(); this.frameStyle = card.getFrameStyle(); id = ability.getId(); this.ability = ability; this.ability.setControllerId(controllerId); if (ability.getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) { spellCards.add(((SplitCard) card).getLeftHalfCard()); spellAbilities.add(((SplitCard) card).getLeftHalfCard().getSpellAbility().copy()); spellCards.add(((SplitCard) card).getRightHalfCard()); spellAbilities.add(((SplitCard) card).getRightHalfCard().getSpellAbility().copy()); } else { spellCards.add(card); spellAbilities.add(ability); } this.controllerId = controllerId; this.fromZone = fromZone; this.countered = false; }
@Override public boolean apply(MageObject input, Game game) { Set<String> cardNames = new HashSet<>(); UUID exileId = CardUtil.getCardExileZoneId(game, sourceId); ExileZone exileZone = game.getExile().getExileZone(exileId); if (exileZone != null) { for (Card card : exileZone.getCards(game)) { cardNames.add(card.getName()); } } // If a player names a card, the player may name either half of a split card, but not both. // A split card has the chosen name if one of its two names matches the chosen name. if (input instanceof SplitCard) { return cardNames.contains(((SplitCard) input).getLeftHalfCard().getName()) || cardNames.contains(((SplitCard) input).getRightHalfCard().getName()); } else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) { SplitCard card = (SplitCard) ((Spell) input).getCard(); return cardNames.contains(card.getLeftHalfCard().getName()) || cardNames.contains(card.getRightHalfCard().getName()); } else { return cardNames.contains(input.getName()); } }
@Override public boolean apply(MageObject input, Game game) { String name = input.getName(); if (input instanceof SplitCard) { return hasTwoWords(((SplitCard)input).getLeftHalfCard().getName()) || hasTwoWords(((SplitCard)input).getRightHalfCard().getName()); } else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED){ SplitCard card = (SplitCard) ((Spell)input).getCard(); return hasTwoWords(card.getLeftHalfCard().getName()) || hasTwoWords(card.getRightHalfCard().getName()); } else { if (name.contains(" // ")) { String leftName = name.substring(0, name.indexOf(" // ")); String rightName = name.substring(name.indexOf(" // ") + 4, name.length()); return hasTwoWords(leftName) || hasTwoWords(rightName); } else { return hasTwoWords(name); } } }
@Override public boolean apply(MageObject input, Game game) { String name = input.getName(); if (input instanceof SplitCard) { return sharesWordWithName(((SplitCard)input).getLeftHalfCard().getName()) || sharesWordWithName(((SplitCard)input).getRightHalfCard().getName()); } else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED){ SplitCard card = (SplitCard) ((Spell)input).getCard(); return sharesWordWithName(card.getLeftHalfCard().getName()) || sharesWordWithName(card.getRightHalfCard().getName()); } else { if (name.contains(" // ")) { String leftName = name.substring(0, name.indexOf(" // ")); String rightName = name.substring(name.indexOf(" // ") + 4, name.length()); return sharesWordWithName(leftName) || sharesWordWithName(rightName); } else { return sharesWordWithName(name); } } }
@Override public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) { switch (ability.getSpellAbilityType()) { case SPLIT_LEFT: return this.getLeftHalfCard().cast(game, fromZone, ability, controllerId); case SPLIT_RIGHT: return this.getRightHalfCard().cast(game, fromZone, ability, controllerId); default: this.getLeftHalfCard().getSpellAbility().setControllerId(controllerId); this.getRightHalfCard().getSpellAbility().setControllerId(controllerId); return super.cast(game, fromZone, ability, controllerId); } }
@Override public LinkedHashMap<UUID, ActivatedAbility> getUseableActivatedAbilities(MageObject object, Zone zone, Game game) { LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<>(); if (object instanceof StackAbility) { // It may not be possible to activate abilities of stack abilities return useable; } if (object instanceof SplitCard) { SplitCard splitCard = (SplitCard) object; getUseableActivatedAbilitiesHalfImpl(splitCard.getLeftHalfCard(), zone, game, splitCard.getLeftHalfCard().getAbilities(), useable); getUseableActivatedAbilitiesHalfImpl(splitCard.getRightHalfCard(), zone, game, splitCard.getRightHalfCard().getAbilities(), useable); getUseableActivatedAbilitiesHalfImpl(splitCard, zone, game, splitCard.getSharedAbilities(), useable); } else { getUseableActivatedAbilitiesHalfImpl(object, zone, game, object.getAbilities(), useable); } getOtherUseableActivatedAbilities(object, zone, game, useable); return useable; }
@Override public boolean apply(MageObject input, Game game) { // If a player names a card, the player may name either half of a split card, but not both. // A split card has the chosen name if one of its two names matches the chosen name. if (input instanceof SplitCard) { return CardUtil.haveSameNames(name, ((SplitCard) input).getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || CardUtil.haveSameNames(name, ((SplitCard) input).getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames); } else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) { SplitCard card = (SplitCard) ((Spell) input).getCard(); return CardUtil.haveSameNames(name, card.getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || CardUtil.haveSameNames(name, card.getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames); } else { if (name.contains(" // ")) { String leftName = name.substring(0, name.indexOf(" // ")); String rightName = name.substring(name.indexOf(" // ") + 4, name.length()); return CardUtil.haveSameNames(leftName, input.getName(), this.ignoreMtgRuleForEmptyNames) || CardUtil.haveSameNames(rightName, input.getName(), this.ignoreMtgRuleForEmptyNames); } else { return CardUtil.haveSameNames(name, input.getName(), this.ignoreMtgRuleForEmptyNames); } } }
@Override public void setZone(Zone zone, Game game) { super.setZone(zone, game); game.setZone(getLeftHalfCard().getId(), zone); game.setZone(getRightHalfCard().getId(), zone); }
@Override public void setZone(Zone zone, Game game) { game.setZone(splitCardParent.getId(), zone); game.setZone(splitCardParent.getLeftHalfCard().getId(), zone); game.setZone(splitCardParent.getRightHalfCard().getId(), zone); }
@Override public void loadCards(Set<Card> cards, UUID ownerId) { for (Card card : cards) { if (card instanceof PermanentCard) { card = ((PermanentCard) card).getCard(); } card.setOwnerId(ownerId); gameCards.put(card.getId(), card); state.addCard(card); if (card.isSplitCard()) { Card leftCard = ((SplitCard) card).getLeftHalfCard(); leftCard.setOwnerId(ownerId); gameCards.put(leftCard.getId(), leftCard); state.addCard(leftCard); Card rightCard = ((SplitCard) card).getRightHalfCard(); rightCard.setOwnerId(ownerId); gameCards.put(rightCard.getId(), rightCard); state.addCard(rightCard); } } }
private boolean isCardFormatValid(Card card, Card commander, FilterMana color) { if (!cardHasValideColor(color, card)) { invalid.put(card.getName(), "Invalid color (" + commander.getName() + ')'); return false; } //905.5b - Converted mana cost must be 3 or less if (card instanceof SplitCard) { if (((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost() > 3) { invalid.put(card.getName(), "Invalid cost (" + ((SplitCard) card).getLeftHalfCard().getManaCost().convertedManaCost() + ')'); return false; } if (((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost() > 3) { invalid.put(card.getName(), "Invalid cost (" + ((SplitCard) card).getRightHalfCard().getManaCost().convertedManaCost() + ')'); return false; } } else if (card.getManaCost().convertedManaCost() > 3) { invalid.put(card.getName(), "Invalid cost (" + card.getManaCost().convertedManaCost() + ')'); return false; } return true; }
public Card copyCard(Card cardToCopy, Ability source, Game game) { Card copiedCard = cardToCopy.copy(); copiedCard.assignNewId(); copiedCard.setOwnerId(source.getControllerId()); copiedCard.setCopy(true, cardToCopy); copiedCards.put(copiedCard.getId(), copiedCard); addCard(copiedCard); if (copiedCard.isSplitCard()) { Card leftCard = ((SplitCard) copiedCard).getLeftHalfCard(); copiedCards.put(leftCard.getId(), leftCard); addCard(leftCard); Card rightCard = ((SplitCard) copiedCard).getRightHalfCard(); copiedCards.put(rightCard.getId(), rightCard); addCard(rightCard); } return copiedCard; }
@Override public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) { if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) { game.getState().setZone(getLeftHalfCard().getId(), toZone); game.getState().setZone(getRightHalfCard().getId(), toZone); return true; } return false; }
@Override public ActivationStatus canActivate(UUID playerId, Game game) { ActivationStatus activationStatus = super.canActivate(playerId, game); if (activationStatus.canActivate()) { Card card = game.getCard(getSourceId()); if (card != null) { // Cards with no Mana Costs cant't be flashbacked (e.g. Ancestral Vision) if (card.getManaCost().isEmpty()) { return ActivationStatus.getFalse(); } // Flashback can never cast a split card by Fuse, because Fuse only works from hand if (card.isSplitCard()) { if (((SplitCard) card).getLeftHalfCard().getName().equals(abilityName)) { return ((SplitCard) card).getLeftHalfCard().getSpellAbility().canActivate(playerId, game); } else if (((SplitCard) card).getRightHalfCard().getName().equals(abilityName)) { return ((SplitCard) card).getRightHalfCard().getSpellAbility().canActivate(playerId, game); } } return card.getSpellAbility().canActivate(playerId, game); } } return activationStatus; }
@Override public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) { if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) { Zone currentZone = game.getState().getZone(getId()); game.getState().setZone(getLeftHalfCard().getId(), currentZone); game.getState().setZone(getRightHalfCard().getId(), currentZone); return true; } return false; }
private boolean isConvertedManaCostEqual(Ability sourceAbility, int amount) { for (Cost cost : sourceAbility.getCosts()) { if (cost.isPaid() && cost instanceof ExileFromHandCost) { for (Card card : ((ExileFromHandCost) cost).getCards()) { if (card instanceof SplitCard) { if (((SplitCard) card).getLeftHalfCard().getConvertedManaCost() == amount) { return true; } if (((SplitCard) card).getRightHalfCard().getConvertedManaCost() == amount) { return true; } } else if (card.getConvertedManaCost() == amount) { return true; } } return false; } } // No alternate costs payed so compare to X value return sourceAbility.getManaCostsToPay().getX() == amount; }
@Override public boolean canChooseTarget(Game game) { if (this instanceof SpellAbility) { if (SpellAbilityType.SPLIT_FUSED.equals(((SpellAbility) this).getSpellAbilityType())) { Card card = game.getCard(getSourceId()); if (card != null) { return canChooseTargetAbility(((SplitCard) card).getLeftHalfCard().getSpellAbility(), game, getControllerId()) && canChooseTargetAbility(((SplitCard) card).getRightHalfCard().getSpellAbility(), game, getControllerId()); } return false; } } return canChooseTargetAbility(this, game, getControllerId()); }
@Override public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (targetPlayer != null && controller != null && sourceObject != null) { String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); Cards hand = targetPlayer.getHand(); for (Card card : hand.getCards(game)) { if (card.isSplitCard()) { SplitCard splitCard = (SplitCard) card; if (CardUtil.haveSameNames(splitCard.getLeftHalfCard().getName(), cardName)) { targetPlayer.discard(card, source, game); } else if (CardUtil.haveSameNames(splitCard.getRightHalfCard().getName(), cardName)) { targetPlayer.discard(card, source, game); } } if (CardUtil.haveSameNames(card.getName(), cardName)) { targetPlayer.discard(card, source, game); } } targetPlayer.revealCards("Cabal Therapy", hand, game); } return true; }
@Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { Player controller = game.getPlayer(controllerId); if (controller != null) { TargetCardInExile target = new TargetCardInExile(new FilterCard(), CardUtil.getCardExileZoneId(game, ability)); target.setNotTarget(true); Cards cards = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, ability)); if (!cards.isEmpty() && controller.choose(Outcome.Benefit, cards, target, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { if (controller.moveCardToGraveyardWithInfo(card, sourceId, game, Zone.EXILED)) { // Split Card check if (card instanceof SplitCard) { game.getState().setValue(sourceId + "_nameOfExiledCardPayment", ((SplitCard) card).getLeftHalfCard().getName()); game.getState().setValue(sourceId + "_nameOfExiledCardPayment2", ((SplitCard) card).getRightHalfCard().getName()); paid = true; return paid; } game.getState().setValue(sourceId + "_nameOfExiledCardPayment", card.getName()); paid = true; } } } } return paid; }