mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
fix that Manamorphose can't be used to cast Imperiosaur (#11620)
This commit is contained in:
parent
5376e81d90
commit
98a3d8b947
2 changed files with 230 additions and 7 deletions
|
|
@ -0,0 +1,216 @@
|
||||||
|
package org.mage.test.cards.abilities.mana;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: game engine does not currently support checkPlayable for mana source filter, hence try/catch for tests
|
||||||
|
*
|
||||||
|
* @author xenohedron
|
||||||
|
*/
|
||||||
|
public class SpendOnlyManaProducedByTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
private static final String imperiosaur = "Imperiosaur"; // 2GG
|
||||||
|
// Spend only mana produced by basic lands to cast this spell.
|
||||||
|
|
||||||
|
private static final String myrSuperion = "Myr Superion"; // 2
|
||||||
|
// Spend only mana produced by creatures to cast this spell.
|
||||||
|
|
||||||
|
private static final String securityRhox = "Security Rhox"; // 2RG
|
||||||
|
// You may pay {R}{G} rather than pay this spell’s mana cost. Spend only mana produced by Treasures to cast it this way.
|
||||||
|
|
||||||
|
private static final String rapaciousDragon = "Rapacious Dragon"; // 4R
|
||||||
|
// When Rapacious Dragon enters the battlefield, create two Treasure tokens.
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImperiosaurPlayable() {
|
||||||
|
addCard(Zone.HAND, playerA, imperiosaur);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, imperiosaur);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, imperiosaur, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tryToCastImperiosaur() {
|
||||||
|
addCard(Zone.HAND, playerA, imperiosaur);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Tree of Tales", 4);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, imperiosaur);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
String expectedError = "Can't find ability to activate command: Cast Imperiosaur";
|
||||||
|
String foundError = "";
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
foundError = e.getMessage();
|
||||||
|
}
|
||||||
|
Assert.assertEquals(expectedError, foundError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tryToCastImperiosaurAgain() {
|
||||||
|
addCard(Zone.HAND, playerA, imperiosaur);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Elvish Mystic", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, imperiosaur);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
String expectedError = "Can't find ability to activate command: Cast Imperiosaur";
|
||||||
|
String foundError = "";
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
foundError = e.getMessage();
|
||||||
|
}
|
||||||
|
Assert.assertEquals(expectedError, foundError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void imperiosaurManamorphose() {
|
||||||
|
String manamorphose = "Manamorphose"; // add two mana in any combination of colors
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, imperiosaur);
|
||||||
|
addCard(Zone.HAND, playerA, manamorphose);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, manamorphose);
|
||||||
|
setChoiceAmount(playerA, 0, 0, 0, 0, 2);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, imperiosaur);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
String expectedError = "Can't find ability to activate command: Cast Imperiosaur";
|
||||||
|
String foundError = "";
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
foundError = e.getMessage();
|
||||||
|
}
|
||||||
|
Assert.assertEquals(expectedError, foundError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tryToCastMyrSuperion() {
|
||||||
|
addCard(Zone.HAND, playerA, myrSuperion);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Wastes", 2);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, myrSuperion);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
String expectedError = "Can't find ability to activate command: Cast Myr Superion";
|
||||||
|
String foundError = "";
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
foundError = e.getMessage();
|
||||||
|
}
|
||||||
|
Assert.assertEquals(expectedError, foundError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void castMyrSuperion() {
|
||||||
|
addCard(Zone.HAND, playerA, myrSuperion);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Palladium Myr");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, myrSuperion);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, myrSuperion, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void castMyrSuperionWithConvoke() {
|
||||||
|
addCard(Zone.HAND, playerA, myrSuperion);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silver Myr");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Chief Engineer"); // artifact creature spells you cast have convoke
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, myrSuperion);
|
||||||
|
addTarget(playerA, "Chief Engineer"); // tap for convoke
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, myrSuperion, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tryToCastMyrSuperionWithConvoke() {
|
||||||
|
addCard(Zone.HAND, playerA, myrSuperion);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Chief Engineer"); // artifact creature spells you cast have convoke
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, myrSuperion);
|
||||||
|
addTarget(playerA, "Chief Engineer"); // tap for convoke
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
String expectedError = "Can't find ability to activate command: Cast Myr Superion";
|
||||||
|
String foundError = "";
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
foundError = e.getMessage();
|
||||||
|
}
|
||||||
|
Assert.assertEquals(expectedError, foundError);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void castSecurityRhox() {
|
||||||
|
addCard(Zone.HAND, playerA, rapaciousDragon);
|
||||||
|
addCard(Zone.HAND, playerA, securityRhox);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rapaciousDragon);
|
||||||
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, securityRhox);
|
||||||
|
setChoice(playerA, true); // pay alternative cost
|
||||||
|
setChoice(playerA, "Red");
|
||||||
|
setChoice(playerA, "Green");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, rapaciousDragon, 1);
|
||||||
|
assertPermanentCount(playerA, securityRhox, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void cantCastSecurityRhox() {
|
||||||
|
addCard(Zone.HAND, playerA, securityRhox);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Taiga", 2);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, securityRhox);
|
||||||
|
setChoice(playerA, true); // pay alternative cost
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
String expectedError = "Can't find ability to activate command: Cast Security Rhox";
|
||||||
|
String foundError = "";
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
} catch (AssertionError e) {
|
||||||
|
foundError = e.getMessage();
|
||||||
|
}
|
||||||
|
Assert.assertEquals(expectedError, foundError);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import mage.MageObject;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
|
import mage.abilities.effects.mana.ManaEffect;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.ManaType;
|
import mage.constants.ManaType;
|
||||||
import mage.constants.TurnPhase;
|
import mage.constants.TurnPhase;
|
||||||
|
|
@ -138,13 +139,19 @@ public class ManaPool implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ManaPoolItem mana : manaItems) {
|
for (ManaPoolItem mana : manaItems) {
|
||||||
if (filter != null) {
|
if (filter != null && !filter.match(mana.getSourceObject(), game)) {
|
||||||
if (!filter.match(mana.getSourceObject(), game)) {
|
// If here, then mana source does not match the filter
|
||||||
// Prevent that cost reduction by convoke is filtered out
|
// However, alternate mana payment abilities such as convoke won't match the filter but are valid
|
||||||
if (!(mana.getSourceObject() instanceof Spell)
|
// So we need to do some ugly checks to allow them
|
||||||
|| ability.getSourceId().equals(mana.getSourceId())) {
|
// For convoke, mana apparently comes from a spell without a mana effect, that doesn't match the ability source
|
||||||
continue;
|
if (ability.getSourceId().equals(mana.getSourceId())
|
||||||
}
|
|| !(mana.getSourceObject() instanceof Spell)
|
||||||
|
|| ((Spell) mana.getSourceObject())
|
||||||
|
.getAbilities(game)
|
||||||
|
.stream()
|
||||||
|
.flatMap(a -> a.getAllEffects().stream())
|
||||||
|
.anyMatch(ManaEffect.class::isInstance)) {
|
||||||
|
continue; // if any of the above cases, not an alt mana payment ability, thus excluded by filter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (possibleAsThoughPoolManaType == null
|
if (possibleAsThoughPoolManaType == null
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue