mirror of
https://github.com/correl/mage.git
synced 2024-11-15 03:00:16 +00:00
* Name card abilities - fixed that it can't find split cards or fused spells with entered name (part of #6603, #6549);
This commit is contained in:
parent
e95ae2675b
commit
4b77cb0fa8
30 changed files with 257 additions and 53 deletions
|
@ -61,7 +61,7 @@ class BileBlightEffect extends BoostAllEffect {
|
|||
} else {
|
||||
String name = target.getName();
|
||||
for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
|
||||
if (CardUtil.haveSameNames(perm.getName(), name)) {
|
||||
if (CardUtil.haveSameNames(perm, name, game)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class BrainPryEffect extends OneShotEffect {
|
|||
if (targetPlayer != null && controller != null && sourceObject != null && cardName != null) {
|
||||
boolean hasDiscarded = false;
|
||||
for (Card card : targetPlayer.getHand().getCards(game)) {
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
targetPlayer.discard(card, source, game);
|
||||
hasDiscarded = true;
|
||||
break;
|
||||
|
|
|
@ -90,18 +90,7 @@ class CabalTherapistDiscardEffect extends OneShotEffect {
|
|||
if (card == null) {
|
||||
return true;
|
||||
}
|
||||
if (card.isSplitCard()) {
|
||||
SplitCard splitCard = (SplitCard) card;
|
||||
if (CardUtil.haveSameNames(splitCard.getLeftHalfCard().getName(), cardName)) {
|
||||
return false;
|
||||
} else if (CardUtil.haveSameNames(splitCard.getRightHalfCard().getName(), cardName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !CardUtil.haveSameNames(card, cardName, game);
|
||||
});
|
||||
targetPlayer.discard(hand, source, game);
|
||||
return true;
|
||||
|
|
|
@ -75,18 +75,7 @@ class CabalTherapyEffect extends OneShotEffect {
|
|||
if (card == null) {
|
||||
return true;
|
||||
}
|
||||
if (card.isSplitCard()) {
|
||||
SplitCard splitCard = (SplitCard) card;
|
||||
if (CardUtil.haveSameNames(splitCard.getLeftHalfCard().getName(), cardName)) {
|
||||
return false;
|
||||
} else if (CardUtil.haveSameNames(splitCard.getRightHalfCard().getName(), cardName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !CardUtil.haveSameNames(card, cardName, game);
|
||||
});
|
||||
targetPlayer.discard(hand, source, game);
|
||||
return true;
|
||||
|
|
|
@ -85,7 +85,7 @@ class ConundrumSphinxEffect extends OneShotEffect {
|
|||
if (card != null) {
|
||||
Cards cards = new CardsImpl(card);
|
||||
player.revealCards(source, player.getName(), cards, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
player.moveCards(cards, Zone.HAND, source, game);
|
||||
} else {
|
||||
player.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
|
|
|
@ -133,7 +133,7 @@ class CorrosiveOozeCombatWatcher extends Watcher {
|
|||
if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) {
|
||||
Permanent attacker = game.getPermanent(event.getTargetId());
|
||||
Permanent blocker = game.getPermanent(event.getSourceId());
|
||||
if (attacker != null && CardUtil.haveSameNames(attacker.getName(), "Corrosive Ooze")) { // To check for name is not working if Ooze is copied but name changed
|
||||
if (attacker != null && CardUtil.haveSameNames(attacker, "Corrosive Ooze", game)) { // To check for name is not working if Ooze is copied but name changed
|
||||
if (blocker != null && hasAttachedEquipment(game, blocker)) {
|
||||
MageObjectReference oozeMor = new MageObjectReference(attacker, game);
|
||||
Set<MageObjectReference> relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>());
|
||||
|
@ -141,7 +141,7 @@ class CorrosiveOozeCombatWatcher extends Watcher {
|
|||
oozeBlocksOrBlocked.put(oozeMor, relatedCreatures);
|
||||
}
|
||||
}
|
||||
if (blocker != null && CardUtil.haveSameNames(blocker.getName(), "Corrosive Ooze")) {
|
||||
if (blocker != null && CardUtil.haveSameNames(blocker, "Corrosive Ooze", game)) {
|
||||
if (attacker != null && hasAttachedEquipment(game, attacker)) {
|
||||
MageObjectReference oozeMor = new MageObjectReference(blocker, game);
|
||||
Set<MageObjectReference> relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>());
|
||||
|
|
|
@ -93,7 +93,7 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec
|
|||
if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
|
||||
MageObject object = game.getObject(event.getSourceId());
|
||||
String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
|
||||
return object != null && CardUtil.haveSameNames(object.getName(), needName);
|
||||
return object != null && CardUtil.haveSameNames(object, needName, game);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ class CouncilOfTheAbsoluteCostReductionEffect extends CostModificationEffectImpl
|
|||
Card card = game.getCard(abilityToModify.getSourceId());
|
||||
if (card != null) {
|
||||
String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
|
||||
return CardUtil.haveSameNames(card.getName(), needName);
|
||||
return CardUtil.haveSameNames(card, needName, game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -61,9 +61,9 @@ class CrownOfEmpiresEffect extends OneShotEffect {
|
|||
boolean scepter = false;
|
||||
boolean throne = false;
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
|
||||
if (CardUtil.haveSameNames(permanent.getName(), "Scepter of Empires")) {
|
||||
if (CardUtil.haveSameNames(permanent, "Scepter of Empires", game)) {
|
||||
scepter = true;
|
||||
} else if (CardUtil.haveSameNames(permanent.getName(), "Throne of Empires")) {
|
||||
} else if (CardUtil.haveSameNames(permanent, "Throne of Empires", game)) {
|
||||
throne = true;
|
||||
}
|
||||
if (scepter && throne) break;
|
||||
|
|
|
@ -70,7 +70,7 @@ class CursedScrollEffect extends OneShotEffect {
|
|||
}
|
||||
revealed.add(card);
|
||||
controller.revealCards(sourceObject.getIdName(), revealed, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
|
||||
if (creature != null) {
|
||||
creature.damage(2, source.getSourceId(), game, false, true);
|
||||
|
|
|
@ -72,6 +72,6 @@ class DeathbellowWarCryTarget extends TargetCardInLibrary {
|
|||
.map(game::getCard)
|
||||
.filter(Objects::nonNull)
|
||||
.map(Card::getName)
|
||||
.noneMatch(n -> CardUtil.haveSameNames(n, card.getName()));
|
||||
.noneMatch(n -> CardUtil.haveSameNames(card, n, game));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ class DementiaSliverEffect extends OneShotEffect {
|
|||
if (card != null) {
|
||||
revealed.add(card);
|
||||
opponent.revealCards(sourceObject.getName(), revealed, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
opponent.discard(card, source, game);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ class DeniedEffect extends OneShotEffect {
|
|||
player.revealCards("Denied!", player.getHand(), game, true);
|
||||
String namedCard = (String) object;
|
||||
for (Card card : player.getHand().getCards(game)) {
|
||||
if (card != null && CardUtil.haveSameNames(card.getName(), namedCard)) {
|
||||
if (card != null && CardUtil.haveSameNames(card, namedCard, game)) {
|
||||
game.getStack().counter(targetSpell.getId(), source.getSourceId(), game);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ class DetentionSphereEntersEffect extends OneShotEffect {
|
|||
} else {
|
||||
String name = targetPermanent.getName();
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
|
||||
if (permanent != null && CardUtil.haveSameNames(permanent.getName(), name)) {
|
||||
if (permanent != null && CardUtil.haveSameNames(permanent, name, game)) {
|
||||
controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ public final class DiviningWitch extends CardImpl {
|
|||
if (card != null) {
|
||||
cardsToReaveal.add(card);
|
||||
// Put that card into your hand
|
||||
if (CardUtil.haveSameNames(card.getName(), name)) {
|
||||
if (CardUtil.haveSameNames(card, name, game)) {
|
||||
cardToHand = card;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ class ForeshadowEffect extends OneShotEffect {
|
|||
Card card = targetPlayer.getLibrary().getFromTop(game);
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.GRAVEYARD, source, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
controller.drawCards(1, source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ class LammastideWeaveEffect extends OneShotEffect {
|
|||
Card card = targetPlayer.getLibrary().getFromTop(game);
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.GRAVEYARD, source, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
controller.gainLife(card.getConvertedManaCost(), game, source);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ class LiarsPendulumEffect extends OneShotEffect {
|
|||
rightGuess = opponentGuess;
|
||||
}
|
||||
}
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
rightGuess = opponentGuess;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ class MagusOfTheScrollEffect extends OneShotEffect {
|
|||
}
|
||||
revealed.add(card);
|
||||
you.revealCards(sourceObject.getName(), revealed, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
|
||||
if (creature != null) {
|
||||
creature.damage(2, source.getSourceId(), game, false, true);
|
||||
|
|
|
@ -78,7 +78,7 @@ class PetraSphinxEffect extends OneShotEffect {
|
|||
if (card != null) {
|
||||
Cards cards = new CardsImpl(card);
|
||||
player.revealCards(source, cards, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
player.moveCards(cards, Zone.HAND, source, game);
|
||||
} else {
|
||||
player.moveCards(cards, Zone.GRAVEYARD, source, game);
|
||||
|
|
|
@ -67,7 +67,7 @@ class PredictEffect extends OneShotEffect {
|
|||
Card card = targetPlayer.getLibrary().getFromTop(game);
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.GRAVEYARD, source, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
amount = 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
|
|||
if (spell != null && spell.isFaceDown(game)) {
|
||||
return false; // Face Down cast spell (Morph creature) has no name
|
||||
}
|
||||
return CardUtil.haveSameNames(card.getName(), creatureName) && Objects.equals(ownerId, card.getOwnerId());
|
||||
return CardUtil.haveSameNames(card, creatureName, game) && Objects.equals(ownerId, card.getOwnerId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ class SearchTheCityExiledCardToHandEffect extends OneShotEffect {
|
|||
ExileZone searchTheCityExileZone = game.getExile().getExileZone(source.getSourceId());
|
||||
if (cardName != null && searchTheCityExileZone != null) {
|
||||
for (Card card : searchTheCityExileZone.getCards(game)) {
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
if (card.moveToZone(Zone.HAND, source.getSourceId(), game, true)) {
|
||||
game.informPlayers("Search the City: put " + card.getName() + " into owner's hand");
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ class SpoilsOfTheVaultEffect extends OneShotEffect {
|
|||
for (Card card : controller.getLibrary().getCards(game)) {
|
||||
if (card != null) {
|
||||
cardsToReveal.add(card);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
controller.moveCards(card, Zone.HAND, source, game);
|
||||
break;
|
||||
} else {
|
||||
|
|
|
@ -86,7 +86,7 @@ class ThoughtHemorrhageEffect extends OneShotEffect {
|
|||
+ targetPlayer.getName(), targetPlayer.getHand(), game);
|
||||
int cardsFound = 0;
|
||||
for (Card card : targetPlayer.getHand().getCards(game)) {
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
cardsFound++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ class TunnelVisionEffect extends OneShotEffect {
|
|||
|
||||
for (Card card : targetPlayer.getLibrary().getCards(game)) {
|
||||
cardsToReveal.add(card);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
namedCard = card;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ class VexingArcanixEffect extends OneShotEffect {
|
|||
if (card != null) {
|
||||
Cards cards = new CardsImpl(card);
|
||||
player.revealCards(sourceObject.getIdName(), cards, game);
|
||||
if (CardUtil.haveSameNames(card.getName(), cardName)) {
|
||||
if (CardUtil.haveSameNames(card, cardName, game)) {
|
||||
player.moveCards(cards, Zone.HAND, source, game);
|
||||
} else {
|
||||
player.moveCards(cards, Zone.GRAVEYARD, source, game);
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
package org.mage.test.cards.split;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CastSplitCardsWithCostModificationTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_CostReduction_Simple() {
|
||||
// {2}{W}{U}
|
||||
// As Council of the Absolute enters the battlefield, choose a noncreature, nonland card name.
|
||||
// Your opponents can’t cast spells with the chosen name.
|
||||
// Spells with the chosen name you cast cost {2} less to cast.
|
||||
addCard(Zone.HAND, playerA, "Council of the Absolute", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
//
|
||||
addCard(Zone.HAND, playerA, "Blastfire Bolt", 1); // {5}{R}, 5 damage
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6 - 2); // -2 for cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 1);
|
||||
|
||||
// cast Council
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Council of the Absolute");
|
||||
setChoice(playerA, "Blastfire Bolt");
|
||||
|
||||
// cast bolt
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Blastfire Bolt", "Balduvian Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerB, "Balduvian Bears", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CostReduction_SplitLeft() {
|
||||
// {2}{W}{U}
|
||||
// As Council of the Absolute enters the battlefield, choose a noncreature, nonland card name.
|
||||
// Your opponents can’t cast spells with the chosen name.
|
||||
// Spells with the chosen name you cast cost {2} less to cast.
|
||||
addCard(Zone.HAND, playerA, "Council of the Absolute", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
//
|
||||
// Armed {1}{R} Target creature gets +1/+1 and gains double strike until end of turn.
|
||||
// Dangerous {3}{G} All creatures able to block target creature this turn do so.
|
||||
addCard(Zone.HAND, playerA, "Armed // Dangerous", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2 - 1); // -1 from cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4 - 2); // check not working right cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
||||
|
||||
// cast Council
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}", 3);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Council of the Absolute");
|
||||
setChoice(playerA, "Armed");
|
||||
|
||||
// cast Armed
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Armed", true);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dangerous", false);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast fused Armed // Dangerous", false);
|
||||
showAvaileableAbilities("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Armed", "Balduvian Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Armed // Dangerous", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CostReduction_SplitRight() {
|
||||
// {2}{W}{U}
|
||||
// As Council of the Absolute enters the battlefield, choose a noncreature, nonland card name.
|
||||
// Your opponents can’t cast spells with the chosen name.
|
||||
// Spells with the chosen name you cast cost {2} less to cast.
|
||||
addCard(Zone.HAND, playerA, "Council of the Absolute", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
//
|
||||
// Armed {1}{R} Target creature gets +1/+1 and gains double strike until end of turn.
|
||||
// Dangerous {3}{G} All creatures able to block target creature this turn do so.
|
||||
addCard(Zone.HAND, playerA, "Armed // Dangerous", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4 - 2); // -2 from cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
||||
|
||||
// cast Council
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}", 3);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Council of the Absolute");
|
||||
setChoice(playerA, "Dangerous");
|
||||
|
||||
// cast Dangerous
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Armed", false);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dangerous", true);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast fused Armed // Dangerous", false);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dangerous", "Balduvian Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Armed // Dangerous", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO: cost modification don't work for fused spells, only for one of the part, see https://github.com/magefree/mage/issues/6603
|
||||
public void test_CostReduction_SplitFused_ReduceRight() {
|
||||
// {2}{W}{U}
|
||||
// As Council of the Absolute enters the battlefield, choose a noncreature, nonland card name.
|
||||
// Your opponents can’t cast spells with the chosen name.
|
||||
// Spells with the chosen name you cast cost {2} less to cast.
|
||||
addCard(Zone.HAND, playerA, "Council of the Absolute", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
//
|
||||
// Armed {1}{R} Target creature gets +1/+1 and gains double strike until end of turn.
|
||||
// Dangerous {3}{G} All creatures able to block target creature this turn do so.
|
||||
addCard(Zone.HAND, playerA, "Armed // Dangerous", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); // no cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4 - 2); // -2 from cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
||||
|
||||
// cast Council
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}", 3);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Council of the Absolute");
|
||||
setChoice(playerA, "Dangerous");
|
||||
|
||||
// cast fused
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Armed", true);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dangerous", true);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast fused Armed // Dangerous", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "fused Armed // Dangerous");
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Armed // Dangerous", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO: cost modification don't work for fused spells, only for one of the part, see https://github.com/magefree/mage/issues/6603
|
||||
public void test_CostReduction_SplitFused_ReduceLeft() {
|
||||
// {2}{W}{U}
|
||||
// As Council of the Absolute enters the battlefield, choose a noncreature, nonland card name.
|
||||
// Your opponents can’t cast spells with the chosen name.
|
||||
// Spells with the chosen name you cast cost {2} less to cast.
|
||||
addCard(Zone.HAND, playerA, "Council of the Absolute", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
//
|
||||
// Armed {1}{R} Target creature gets +1/+1 and gains double strike until end of turn.
|
||||
// Dangerous {3}{G} All creatures able to block target creature this turn do so.
|
||||
addCard(Zone.HAND, playerA, "Armed // Dangerous", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2 - 1); // -1 from cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4 - 1); // -1 from cost reduction ON FUSED
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1);
|
||||
|
||||
// cast Council
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}", 3);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Council of the Absolute");
|
||||
setChoice(playerA, "Armed");
|
||||
|
||||
// cast fused
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Armed", true);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dangerous", true);
|
||||
checkPlayableAbility("after reduction", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast fused Armed // Dangerous", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "fused Armed // Dangerous");
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Armed // Dangerous", 1);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package org.mage.test.testapi;
|
||||
|
||||
import mage.cards.Card;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.EmptyNames;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
|
@ -44,6 +46,18 @@ public class TestAliases extends CardTestPlayerBase {
|
|||
Assert.assertFalse(CardUtil.haveSameNames("Name", "123", true));
|
||||
Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString(), true));
|
||||
Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2", true));
|
||||
|
||||
// name with split card
|
||||
Card splitCard1 = CardRepository.instance.findCard("Armed // Dangerous").getCard();
|
||||
Card splitCard2 = CardRepository.instance.findCard("Alive // Well").getCard();
|
||||
Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Armed", currentGame));
|
||||
Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Dangerous", currentGame));
|
||||
Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Armed // Dangerous", currentGame));
|
||||
Assert.assertTrue(CardUtil.haveSameNames(splitCard1, splitCard1));
|
||||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other", currentGame));
|
||||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other // Dangerous", currentGame));
|
||||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Armed // Other", currentGame));
|
||||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, splitCard2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -31,11 +31,13 @@ public class NamePredicate implements Predicate<MageObject> {
|
|||
// 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);
|
||||
CardUtil.haveSameNames(name, ((SplitCard) input).getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
CardUtil.haveSameNames(name, input.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);
|
||||
CardUtil.haveSameNames(name, card.getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) ||
|
||||
CardUtil.haveSameNames(name, card.getName(), this.ignoreMtgRuleForEmptyNames);
|
||||
} else {
|
||||
if (name.contains(" // ")) {
|
||||
String leftName = name.substring(0, name.indexOf(" // "));
|
||||
|
|
|
@ -11,6 +11,7 @@ import mage.constants.ColoredManaSymbol;
|
|||
import mage.constants.EmptyNames;
|
||||
import mage.constants.ManaType;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.game.CardState;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -657,6 +658,14 @@ public final class CardUtil {
|
|||
return object1 != null && object2 != null && haveSameNames(object1.getName(), object2.getName());
|
||||
}
|
||||
|
||||
public static boolean haveSameNames(MageObject object, String needName, Game game) {
|
||||
return containsName(object, needName, game);
|
||||
}
|
||||
|
||||
public static boolean containsName(MageObject object, String name, Game game) {
|
||||
return new NamePredicate(name).apply(object, game);
|
||||
}
|
||||
|
||||
public static boolean haveEmptyName(String name) {
|
||||
return name == null || name.isEmpty() || name.equals(EmptyNames.FACE_DOWN_CREATURE.toString()) || name.equals(EmptyNames.FACE_DOWN_TOKEN.toString());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue