mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
* Fixed a problem where for copies of cards/permanent the included spell ability was not correctly copied and the copied card had the spell ability twice. That could cause in some rare cases problems with spell ids of copies (this fixes #6824) or did allow on the other side some unproper handling of things (Animate Dead).
This commit is contained in:
parent
9f92377eef
commit
eecaa232f5
12 changed files with 300 additions and 149 deletions
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.u;
|
package mage.cards.u;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
import mage.abilities.effects.common.ShuffleIntoLibraryTargetEffect;
|
import mage.abilities.effects.common.ShuffleIntoLibraryTargetEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
|
@ -8,8 +8,6 @@ import mage.constants.CardType;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
|
@ -17,7 +15,7 @@ import java.util.UUID;
|
||||||
public final class UnravelTheAether extends CardImpl {
|
public final class UnravelTheAether extends CardImpl {
|
||||||
|
|
||||||
public UnravelTheAether(UUID ownerId, CardSetInfo setInfo) {
|
public UnravelTheAether(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
|
||||||
|
|
||||||
// Choose target artifact or enchantment. Its owner shuffles it into their library.
|
// Choose target artifact or enchantment. Its owner shuffles it into their library.
|
||||||
this.getSpellAbility().addEffect(new ShuffleIntoLibraryTargetEffect());
|
this.getSpellAbility().addEffect(new ShuffleIntoLibraryTargetEffect());
|
||||||
|
|
|
@ -16,8 +16,8 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
Enchantment - Aura Curse
|
Enchantment - Aura Curse
|
||||||
Enchant player
|
Enchant player
|
||||||
At the beginning of enchanted player's upkeep, that player sacrifices a creature or planeswalker. If the player can't, they lose 5 life.
|
At the beginning of enchanted player's upkeep, that player sacrifices a creature or planeswalker. If the player can't, they lose 5 life.
|
||||||
*/
|
*/
|
||||||
private String cReality = "Cruel Reality";
|
private final String cReality = "Cruel Reality";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCurseOfBloodletting() {
|
public void testCurseOfBloodletting() {
|
||||||
|
@ -29,7 +29,6 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerA);
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerA);
|
||||||
|
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
|
||||||
// Enchant player
|
// Enchant player
|
||||||
// Whenever enchanted player casts an instant or sorcery spell, each other player may copy that
|
// Whenever enchanted player casts an instant or sorcery spell, each other player may copy that
|
||||||
// spell and may choose new targets for the copy they control.
|
// spell and may choose new targets for the copy they control.
|
||||||
addCard(Zone.HAND, playerA, "Curse of Echoes");
|
addCard(Zone.HAND, playerA, "Curse of Echoes");
|
||||||
// Draw three cards.
|
// Draw three cards.
|
||||||
addCard(Zone.HAND, playerB, "Jace's Ingenuity");
|
addCard(Zone.HAND, playerB, "Jace's Ingenuity");
|
||||||
|
@ -71,7 +70,6 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
|
||||||
|
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
@ -90,7 +88,6 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
@ -102,64 +99,59 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
* Checks if Copy Enchantment works for player auras
|
* Checks if Copy Enchantment works for player auras
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCurseOfExhaustion3() {
|
public void testCurseOfExhaustion3() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
|
||||||
|
|
||||||
// Enchant player
|
// Enchant player
|
||||||
// Enchanted player can't cast more than one spell each turn.
|
// Enchanted player can't cast more than one spell each turn.
|
||||||
addCard(Zone.HAND, playerA, "Curse of Exhaustion");
|
addCard(Zone.HAND, playerA, "Curse of Exhaustion");
|
||||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
|
||||||
|
|
||||||
addCard(Zone.HAND, playerB, "Copy Enchantment", 1);
|
addCard(Zone.HAND, playerB, "Copy Enchantment", 1);
|
||||||
|
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of Exhaustion", playerB);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of Exhaustion", playerB);
|
||||||
|
|
||||||
castSpell(4, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
castSpell(4, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Copy Enchantment");
|
castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Copy Enchantment");
|
||||||
setChoice(playerB, "Yes");
|
setChoice(playerB, "Yes");
|
||||||
setChoice(playerB, "Curse of Exhaustion");
|
setChoice(playerB, "Curse of Exhaustion");
|
||||||
setChoice(playerB, "targetPlayer=PlayerA");
|
setChoice(playerB, "targetPlayer=PlayerA");
|
||||||
castSpell(4, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
castSpell(4, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setStopAt(4, PhaseStep.END_TURN);
|
setStopAt(4, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertHandCount(playerB, "Copy Enchantment", 0);
|
assertHandCount(playerB, "Copy Enchantment", 0);
|
||||||
assertGraveyardCount(playerB, "Copy Enchantment", 0);
|
assertGraveyardCount(playerB, "Copy Enchantment", 0);
|
||||||
|
|
||||||
assertPermanentCount(playerA, "Curse of Exhaustion", 1);
|
assertPermanentCount(playerA, "Curse of Exhaustion", 1);
|
||||||
assertPermanentCount(playerB, "Curse of Exhaustion", 1);
|
assertPermanentCount(playerB, "Curse of Exhaustion", 1);
|
||||||
|
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 17);
|
assertLife(playerB, 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returng curse enchantment from graveyard to battlefield
|
// returng curse enchantment from graveyard to battlefield
|
||||||
@Test
|
@Test
|
||||||
public void testCurseOfExhaustion4() {
|
public void testCurseOfExhaustion4() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
|
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||||
|
|
||||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
|
||||||
|
|
||||||
addCard(Zone.GRAVEYARD, playerB, "Curse of Exhaustion", 1);
|
addCard(Zone.GRAVEYARD, playerB, "Curse of Exhaustion", 1);
|
||||||
addCard(Zone.HAND, playerB, "Obzedat's Aid", 1);
|
addCard(Zone.HAND, playerB, "Obzedat's Aid", 1);
|
||||||
|
|
||||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Obzedat's Aid", "Curse of Exhaustion");
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Obzedat's Aid", "Curse of Exhaustion");
|
||||||
setChoice(playerB, "PlayerA");
|
setChoice(playerB, "PlayerA");
|
||||||
|
|
||||||
|
|
||||||
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
|
||||||
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
|
||||||
|
|
||||||
|
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
|
||||||
setStopAt(2, PhaseStep.END_TURN);
|
setStopAt(2, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
@ -167,13 +159,13 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
assertHandCount(playerB, "Obzedat's Aid", 0);
|
assertHandCount(playerB, "Obzedat's Aid", 0);
|
||||||
assertGraveyardCount(playerB, "Obzedat's Aid", 1);
|
assertGraveyardCount(playerB, "Obzedat's Aid", 1);
|
||||||
assertGraveyardCount(playerB, "Curse of Exhaustion", 0);
|
assertGraveyardCount(playerB, "Curse of Exhaustion", 0);
|
||||||
|
|
||||||
assertPermanentCount(playerB, "Curse of Exhaustion", 1);
|
assertPermanentCount(playerB, "Curse of Exhaustion", 1);
|
||||||
|
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 17);
|
assertLife(playerB, 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCurseOfThirst1() {
|
public void testCurseOfThirst1() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
|
||||||
|
@ -240,10 +232,9 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 20);
|
assertLife(playerB, 20);
|
||||||
assertPermanentCount(playerA, "Curse of Misfortunes", 1);
|
assertPermanentCount(playerA, "Curse of Misfortunes", 1);
|
||||||
assertPermanentCount(playerA, "Curse of Bloodletting", 1);
|
assertPermanentCount(playerA, "Curse of Bloodletting", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCurseOfDeathsHold() {
|
public void testCurseOfDeathsHold() {
|
||||||
// Creatures enchanted player controls get -1/-1.
|
// Creatures enchanted player controls get -1/-1.
|
||||||
|
@ -251,7 +242,7 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
|
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of Death's Hold", playerB);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of Death's Hold", playerB);
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.END_COMBAT);
|
setStopAt(1, PhaseStep.END_COMBAT);
|
||||||
|
@ -259,12 +250,12 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 20);
|
assertLife(playerB, 20);
|
||||||
|
|
||||||
assertPermanentCount(playerA, "Curse of Death's Hold", 1);
|
assertPermanentCount(playerA, "Curse of Death's Hold", 1);
|
||||||
|
|
||||||
assertPowerToughness(playerB, "Silvercoat Lion", 1, 1);
|
assertPowerToughness(playerB, "Silvercoat Lion", 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCurseOfDeathsHold2() {
|
public void testCurseOfDeathsHold2() {
|
||||||
// Creatures enchanted player controls get -1/-1.
|
// Creatures enchanted player controls get -1/-1.
|
||||||
|
@ -276,31 +267,29 @@ public class CursesTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
|
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Forest", 3);
|
addCard(Zone.BATTLEFIELD, playerB, "Forest", 3);
|
||||||
addCard(Zone.HAND, playerB, "Reclamation Sage");
|
addCard(Zone.HAND, playerB, "Reclamation Sage");
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of Death's Hold", playerB);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of Death's Hold", playerB);
|
||||||
|
|
||||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Reclamation Sage");
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Reclamation Sage");
|
||||||
addTarget(playerB, "Curse of Death's Hold");
|
addTarget(playerB, "Curse of Death's Hold");
|
||||||
|
|
||||||
// {2}{G/U}{G/U}: Put the top two cards of your library into your graveyard, then return a nonland card of an opponent's choice from your graveyard to your hand.
|
// {2}{G/U}{G/U}: Put the top two cards of your library into your graveyard, then return a nonland card of an opponent's choice from your graveyard to your hand.
|
||||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{G/U}{G/U}: Mill two cards");
|
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}{G/U}{G/U}: Mill two cards");
|
||||||
castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Curse of Death's Hold", playerB);
|
castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Curse of Death's Hold", playerB);
|
||||||
|
|
||||||
setStopAt(3, PhaseStep.END_TURN);
|
setStopAt(3, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 20);
|
assertLife(playerB, 20);
|
||||||
|
|
||||||
assertGraveyardCount(playerB, "Reclamation Sage", 1);
|
assertGraveyardCount(playerB, "Reclamation Sage", 1);
|
||||||
assertPermanentCount(playerA, "Curse of Death's Hold", 1);
|
assertPermanentCount(playerA, "Curse of Death's Hold", 1);
|
||||||
assertGraveyardCount(playerA, 2);
|
assertGraveyardCount(playerA, 2);
|
||||||
|
|
||||||
assertPowerToughness(playerB, "Silvercoat Lion", 1, 1);
|
assertPowerToughness(playerB, "Silvercoat Lion", 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void cruelRealityHasBothCreatureAndPwChoosePw() {
|
public void cruelRealityHasBothCreatureAndPwChoosePw() {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.mage.test.cards.abilities.oneshot.counterspell;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
@ -99,4 +98,76 @@ public class CounterspellTest extends CardTestPlayerBase {
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 17);
|
assertLife(playerB, 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyCounterToCounterGraveyard() {
|
||||||
|
// Lightning Bolt deals 3 damage to any target.
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||||
|
// Copy target instant or sorcery spell. You may choose new targets for the copy.
|
||||||
|
addCard(Zone.HAND, playerA, "Twincast");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
|
||||||
|
// Counter target spell
|
||||||
|
addCard(Zone.HAND, playerB, "Counterspell"); // Instant {1}{U}
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Counterspell", "Lightning Bolt");
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Twincast", "Counterspell");
|
||||||
|
|
||||||
|
setChoice(playerA, "Yes"); // change the target
|
||||||
|
addTarget(playerA, "Counterspell");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Lightning Bolt", 1);
|
||||||
|
assertGraveyardCount(playerA, "Twincast", 1);
|
||||||
|
|
||||||
|
assertGraveyardCount(playerB, "Counterspell", 1);
|
||||||
|
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
assertLife(playerB, 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyCounterToCounterExile() {
|
||||||
|
// Lightning Bolt deals 3 damage to any target.
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||||
|
// Copy target instant or sorcery spell. You may choose new targets for the copy.
|
||||||
|
addCard(Zone.HAND, playerA, "Twincast");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
|
||||||
|
// CCounter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard.
|
||||||
|
addCard(Zone.HAND, playerB, "Dissipate"); // Instant {1}{U}
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Dissipate", "Lightning Bolt");
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Twincast", "Dissipate");
|
||||||
|
|
||||||
|
setChoice(playerA, "Yes"); // change the target
|
||||||
|
addTarget(playerA, "Dissipate");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Lightning Bolt", 1);
|
||||||
|
assertGraveyardCount(playerA, "Twincast", 1);
|
||||||
|
|
||||||
|
assertExileCount(playerB, "Dissipate", 1);
|
||||||
|
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
assertLife(playerB, 17);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package org.mage.test.cards.enchantments;
|
package org.mage.test.cards.enchantments;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
|
@ -119,7 +118,7 @@ public class AnimateDeadTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cruel Edict", playerA);
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cruel Edict", playerA);
|
||||||
|
|
||||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
setStopAt(2, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertGraveyardCount(playerB, "Cruel Edict", 1);
|
assertGraveyardCount(playerB, "Cruel Edict", 1);
|
||||||
|
@ -168,6 +167,8 @@ public class AnimateDeadTest extends CardTestPlayerBase {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAnimateAndDragonlordAtarkaWithNoTargets() {
|
public void testAnimateAndDragonlordAtarkaWithNoTargets() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
|
||||||
// Enchant creature card in a graveyard
|
// Enchant creature card in a graveyard
|
||||||
|
@ -188,6 +189,11 @@ public class AnimateDeadTest extends CardTestPlayerBase {
|
||||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertLife(playerA, 20);
|
||||||
|
assertLife(playerB, 20);
|
||||||
|
|
||||||
assertPermanentCount(playerA, "Animate Dead", 1);
|
assertPermanentCount(playerA, "Animate Dead", 1);
|
||||||
assertPermanentCount(playerA, "Dragonlord Atarka", 1);
|
assertPermanentCount(playerA, "Dragonlord Atarka", 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,8 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testWithAnimateDead() {
|
public void testWithAnimateDead() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
|
||||||
// When Worldgorger Dragon enters the battlefield, exile all other permanents you control.
|
// When Worldgorger Dragon enters the battlefield, exile all other permanents you control.
|
||||||
|
@ -79,6 +81,7 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
// Enchanted creature gets -1/-0.
|
// Enchanted creature gets -1/-0.
|
||||||
addCard(Zone.HAND, playerA, "Animate Dead");
|
addCard(Zone.HAND, playerA, "Animate Dead");
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
|
||||||
// Instant {X}{R}{R}
|
// Instant {X}{R}{R}
|
||||||
// Volcanic Geyser deals X damage to any target.
|
// Volcanic Geyser deals X damage to any target.
|
||||||
addCard(Zone.HAND, playerA, "Volcanic Geyser", 1);
|
addCard(Zone.HAND, playerA, "Volcanic Geyser", 1);
|
||||||
|
@ -86,44 +89,61 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Staunch Defenders", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Staunch Defenders", 1);
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Animate Dead", "Worldgorger Dragon");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Animate Dead", "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
setChoice(playerA, "No");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB, 22);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB, 22);
|
||||||
setChoice(playerA, "X=20");
|
setChoice(playerA, "X=20");
|
||||||
|
|
||||||
// not an infinite loop resulting in a draw
|
|
||||||
for (int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
setChoice(playerA, "No");
|
|
||||||
setChoice(playerB, "No");
|
|
||||||
}
|
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
assertLife(playerA, 44);
|
assertLife(playerA, 44);
|
||||||
assertLife(playerB, 0);
|
assertLife(playerB, 0);
|
||||||
|
|
||||||
|
@ -132,7 +152,7 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* v9: Worldgorger Dragon + Animate Dead is still acting up (yey complex
|
* v9: Worldgorger Dragon + Animate Dead is still acting up (yet complex
|
||||||
* rules interactions!). The first time you return Animate Dead from
|
* rules interactions!). The first time you return Animate Dead from
|
||||||
* Worldgorger's exile, it works like it's supposed to. You have to pick a
|
* Worldgorger's exile, it works like it's supposed to. You have to pick a
|
||||||
* creature, and it brings it back. But if you pick Worldgorger Dragon
|
* creature, and it brings it back. But if you pick Worldgorger Dragon
|
||||||
|
@ -149,6 +169,8 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testWithAnimateDeadDifferentTargets() {
|
public void testWithAnimateDeadDifferentTargets() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
|
||||||
// When Worldgorger Dragon enters the battlefield, exile all other permanents you control.
|
// When Worldgorger Dragon enters the battlefield, exile all other permanents you control.
|
||||||
|
@ -161,9 +183,9 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
// under your control and attach Animate Dead to it. When Animate Dead leaves the battlefield, that creature's controller sacrifices it.
|
// under your control and attach Animate Dead to it. When Animate Dead leaves the battlefield, that creature's controller sacrifices it.
|
||||||
addCard(Zone.HAND, playerA, "Animate Dead");
|
addCard(Zone.HAND, playerA, "Animate Dead");
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
// Instant {X}{R}{R}
|
|
||||||
// Volcanic Geyser deals X damage to any target.
|
// Volcanic Geyser deals X damage to any target.
|
||||||
addCard(Zone.HAND, playerA, "Volcanic Geyser", 1);
|
addCard(Zone.HAND, playerA, "Volcanic Geyser", 1);// Instant {X}{R}{R}
|
||||||
// When Staunch Defenders enters the battlefield, you gain 4 life.
|
// When Staunch Defenders enters the battlefield, you gain 4 life.
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Staunch Defenders", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Staunch Defenders", 1);
|
||||||
|
|
||||||
|
@ -176,13 +198,15 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
setChoice(playerA, "Worldgorger Dragon");
|
setChoice(playerA, "Worldgorger Dragon");
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
|
||||||
setChoice(playerA, "Silvercoat Lion");
|
setChoice(playerA, "Silvercoat Lion");
|
||||||
|
|
||||||
|
setChoice(playerA, "When {this} enters the battlefield, if it's");
|
||||||
|
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
@ -193,6 +217,8 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
|
||||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Volcanic Geyser", 1);
|
assertGraveyardCount(playerA, "Volcanic Geyser", 1);
|
||||||
assertGraveyardCount(playerA, "Worldgorger Dragon", 1);
|
assertGraveyardCount(playerA, "Worldgorger Dragon", 1);
|
||||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package org.mage.test.turnmod;
|
package org.mage.test.turnmod;
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
|
@ -97,4 +96,50 @@ public class ExtraTurnsTest extends CardTestPlayerBase {
|
||||||
Assert.assertEquals("For turn " + currentGame.getTurnNum() + ", playerB has to be the active player but active player is: "
|
Assert.assertEquals("For turn " + currentGame.getTurnNum() + ", playerB has to be the active player but active player is: "
|
||||||
+ currentGame.getPlayer(currentGame.getActivePlayerId()).getName(), currentGame.getActivePlayerId(), playerB.getId());
|
+ currentGame.getPlayer(currentGame.getActivePlayerId()).getName(), currentGame.getActivePlayerId(), playerB.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/magefree/mage/issues/6824
|
||||||
|
*
|
||||||
|
* When you cast miracled Temporal Mastery with God-Eternal Kefnet on the
|
||||||
|
* battlefield and copy it with it's ability you get only 1 extra turn. It
|
||||||
|
* should be 2, since you cast Temporal Mastery with it's miracle ability +
|
||||||
|
* you get a copy from Kefnet's ability. Still after first extra turn game
|
||||||
|
* proceeds to next player.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCopyMiracledTemporalMastery4TwoExtraTurns() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 7);
|
||||||
|
// Flying
|
||||||
|
// You may reveal the first card you draw each turn as you draw it. Whenever you reveal an instant or sorcery card this way,
|
||||||
|
// copy that card and you may cast the copy. That copy costs {2} less to cast.
|
||||||
|
// When God-Eternal Kefnet dies or is put into exile from the battlefield, you may put it into its owner’s library third from the top.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "God-Eternal Kefnet", 1);
|
||||||
|
// Take an extra turn after this one. Exile Temporal Mastery.
|
||||||
|
// Miracle {1}{U} (You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn.)
|
||||||
|
addCard(Zone.LIBRARY, playerB, "Temporal Mastery", 1); // Sorcery {5}{U}{U}
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
setChoice(playerB, "Yes"); // Would you like to reveal first drawn card (Temporal Mastery, you can copy it and cast {2} less)?
|
||||||
|
setChoice(playerB, "Yes"); // Would you like to copy Temporal Mastery and cast it {2} less?
|
||||||
|
setChoice(playerB, "Yes"); // Reveal Temporal Mastery to be able to use Miracle?
|
||||||
|
setChoice(playerB, "Yes"); // Miracle {1}{U} (You may cast this card for its miracle cost when you draw it if it's the first card you drew this turn.)
|
||||||
|
|
||||||
|
setChoice(playerB, "No"); // Would you like to reveal first drawn card? (Turn 3)
|
||||||
|
setChoice(playerB, "No"); // Would you like to reveal first drawn card? (Turn 4)
|
||||||
|
|
||||||
|
// Turn 3 + 4 are extra turns
|
||||||
|
setStopAt(4, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertExileCount(playerB, "Temporal Mastery", 1);
|
||||||
|
|
||||||
|
Assert.assertTrue("Turn 4 is an extra turn ", currentGame.getState().isExtraTurn());
|
||||||
|
Assert.assertEquals("For turn " + currentGame.getTurnNum() + ", playerB has to be the active player but active player is: "
|
||||||
|
+ currentGame.getPlayer(currentGame.getActivePlayerId()).getName(), currentGame.getActivePlayerId(), playerB.getId());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
package mage.abilities.effects;
|
package mage.abilities.effects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.target.targetpointer.TargetPointer;
|
import mage.target.targetpointer.TargetPointer;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class Effects extends ArrayList<Effect> {
|
public class Effects extends ArrayList<Effect> {
|
||||||
|
|
||||||
public Effects(Effect... effects) {
|
public Effects(Effect... effects) {
|
||||||
for (Effect effect : effects) {
|
this.addAll(Arrays.asList(effects));
|
||||||
this.add(effect);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Effects(final Effects effects) {
|
public Effects(final Effects effects) {
|
||||||
|
@ -64,15 +62,15 @@ public class Effects extends ArrayList<Effect> {
|
||||||
endString = " ";
|
endString = " ";
|
||||||
} else if (nextRule.startsWith(",") || nextRule.startsWith(" ")) {
|
} else if (nextRule.startsWith(",") || nextRule.startsWith(" ")) {
|
||||||
endString = "";
|
endString = "";
|
||||||
// nextRule determined to be a new sentence, now check ending of lastRule
|
// nextRule determined to be a new sentence, now check ending of lastRule
|
||||||
} else if (lastRule != null && lastRule.length() > 3) {
|
} else if (lastRule != null && lastRule.length() > 3) {
|
||||||
//check if lastRule already has appropriate punctuation, if so, add a space.
|
//check if lastRule already has appropriate punctuation, if so, add a space.
|
||||||
if (lastRule.endsWith(".\"") ||
|
if (lastRule.endsWith(".\"")
|
||||||
lastRule.endsWith(".)") ||
|
|| lastRule.endsWith(".)")
|
||||||
lastRule.endsWith(".)</i>") ||
|
|| lastRule.endsWith(".)</i>")
|
||||||
lastRule.endsWith(".")){
|
|| lastRule.endsWith(".")) {
|
||||||
endString = " ";
|
endString = " ";
|
||||||
// if lastRule does not have appropriate punctuation, add the default ". "
|
// if lastRule does not have appropriate punctuation, add the default ". "
|
||||||
} else if (!lastRule.endsWith(".") && !lastRule.endsWith("<br>")) {
|
} else if (!lastRule.endsWith(".") && !lastRule.endsWith("<br>")) {
|
||||||
endString = ". ";
|
endString = ". ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
|
@ -102,9 +101,7 @@ public class MiracleAbility extends TriggeredAbilityImpl {
|
||||||
public boolean checkTrigger(GameEvent event, Game game) {
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
if (event.getSourceId().equals(getSourceId())) {
|
if (event.getSourceId().equals(getSourceId())) {
|
||||||
// Refer to the card at the zone it is now (hand)
|
// Refer to the card at the zone it is now (hand)
|
||||||
FixedTarget fixedTarget = new FixedTarget(event.getSourceId());
|
getEffects().setTargetPointer(new FixedTarget(game.getCard(event.getSourceId()), game));
|
||||||
fixedTarget.init(game, this);
|
|
||||||
getEffects().get(0).setTargetPointer(fixedTarget);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
package mage.cards;
|
package mage.cards;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.MageObjectImpl;
|
import mage.MageObjectImpl;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
@ -27,13 +33,6 @@ import mage.util.SubTypeList;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public abstract class CardImpl extends MageObjectImpl implements Card {
|
public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -137,7 +136,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
nightCard = card.nightCard;
|
nightCard = card.nightCard;
|
||||||
}
|
}
|
||||||
if (card.spellAbility != null) {
|
if (card.spellAbility != null) {
|
||||||
spellAbility = card.getSpellAbility().copy();
|
spellAbility = (SpellAbility) abilities.get(0);
|
||||||
} else {
|
} else {
|
||||||
spellAbility = null;
|
spellAbility = null;
|
||||||
}
|
}
|
||||||
|
@ -397,10 +396,15 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamic cost modification for card (process only own abilities).
|
* Dynamic cost modification for card (process only own abilities). Example:
|
||||||
* Example: if it need stack related info (like real targets) then must check two states (game.inCheckPlayableState):
|
* if it need stack related info (like real targets) then must check two
|
||||||
* 1. In playable state it must check all possible use cases (e.g. allow to reduce on any available target and modes)
|
* states (game.inCheckPlayableState):
|
||||||
* 2. In real cast state it must check current use case (e.g. real selected targets and modes)
|
*
|
||||||
|
* 1. In playable state it must check all possible use cases (e.g. allow to
|
||||||
|
* reduce on any available target and modes)
|
||||||
|
*
|
||||||
|
* 2. In real cast state it must check current use case (e.g. real selected
|
||||||
|
* targets and modes)
|
||||||
*
|
*
|
||||||
* @param ability
|
* @param ability
|
||||||
* @param game
|
* @param game
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package mage.game.permanent;
|
package mage.game.permanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.annotation.processing.SupportedSourceVersion;
|
||||||
|
import javax.lang.model.SourceVersion;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Abilities;
|
import mage.abilities.Abilities;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
import mage.abilities.costs.mana.ManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCosts;
|
import mage.abilities.costs.mana.ManaCosts;
|
||||||
import mage.abilities.keyword.TransformAbility;
|
import mage.abilities.keyword.TransformAbility;
|
||||||
|
@ -11,11 +15,10 @@ import mage.cards.LevelerCard;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
public class PermanentCard extends PermanentImpl {
|
public class PermanentCard extends PermanentImpl {
|
||||||
|
|
||||||
protected int maxLevelCounters;
|
protected int maxLevelCounters;
|
||||||
|
@ -86,6 +89,9 @@ public class PermanentCard extends PermanentImpl {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.abilities = card.getAbilities().copy();
|
this.abilities = card.getAbilities().copy();
|
||||||
|
if (this.spellAbility != null) {
|
||||||
|
this.spellAbility = (SpellAbility) this.abilities.get(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// adventure cards must show adventure spell info on battlefield too
|
// adventure cards must show adventure spell info on battlefield too
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package mage.game.stack;
|
package mage.game.stack;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
@ -13,7 +14,6 @@ import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.mana.ActivationManaAbilityStep;
|
import mage.abilities.costs.mana.ActivationManaAbilityStep;
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
import mage.abilities.costs.mana.ManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCosts;
|
import mage.abilities.costs.mana.ManaCosts;
|
||||||
import mage.abilities.keyword.BestowAbility;
|
|
||||||
import mage.abilities.keyword.MorphAbility;
|
import mage.abilities.keyword.MorphAbility;
|
||||||
import mage.abilities.text.TextPart;
|
import mage.abilities.text.TextPart;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
|
@ -32,8 +32,6 @@ import mage.players.Player;
|
||||||
import mage.util.GameLog;
|
import mage.util.GameLog;
|
||||||
import mage.util.SubTypeList;
|
import mage.util.SubTypeList;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
|
@ -326,7 +324,7 @@ public class Spell extends StackObjImpl implements Card {
|
||||||
*/
|
*/
|
||||||
private boolean spellAbilityCheckTargetsAndDeactivateModes(SpellAbility spellAbility, Game game) {
|
private boolean spellAbilityCheckTargetsAndDeactivateModes(SpellAbility spellAbility, Game game) {
|
||||||
boolean legalModes = false;
|
boolean legalModes = false;
|
||||||
for (Iterator<UUID> iterator = spellAbility.getModes().getSelectedModes().iterator(); iterator.hasNext(); ) {
|
for (Iterator<UUID> iterator = spellAbility.getModes().getSelectedModes().iterator(); iterator.hasNext();) {
|
||||||
UUID nextSelectedModeId = iterator.next();
|
UUID nextSelectedModeId = iterator.next();
|
||||||
Mode mode = spellAbility.getModes().get(nextSelectedModeId);
|
Mode mode = spellAbility.getModes().get(nextSelectedModeId);
|
||||||
if (!mode.getTargets().isEmpty()) {
|
if (!mode.getTargets().isEmpty()) {
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package mage.players;
|
package mage.players;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import mage.ConditionalMana;
|
import mage.ConditionalMana;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
|
@ -66,11 +70,6 @@ import mage.util.GameLog;
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public abstract class PlayerImpl implements Player, Serializable {
|
public abstract class PlayerImpl implements Player, Serializable {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(PlayerImpl.class);
|
private static final Logger logger = Logger.getLogger(PlayerImpl.class);
|
||||||
|
@ -179,7 +178,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
|
|
||||||
// Used during available mana calculation to give back possible available net mana from triggered mana abilities (No need to copy)
|
// Used during available mana calculation to give back possible available net mana from triggered mana abilities (No need to copy)
|
||||||
protected final List<List<Mana>> availableTriggeredManaList = new ArrayList<>();
|
protected final List<List<Mana>> availableTriggeredManaList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* During some steps we can't play anything
|
* During some steps we can't play anything
|
||||||
*/
|
*/
|
||||||
|
@ -610,9 +609,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
&& this.hasOpponent(sourceControllerId, game)
|
&& this.hasOpponent(sourceControllerId, game)
|
||||||
&& game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) == null
|
&& game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) == null
|
||||||
&& abilities.stream()
|
&& abilities.stream()
|
||||||
.filter(HexproofBaseAbility.class::isInstance)
|
.filter(HexproofBaseAbility.class::isInstance)
|
||||||
.map(HexproofBaseAbility.class::cast)
|
.map(HexproofBaseAbility.class::cast)
|
||||||
.anyMatch(ability -> ability.checkObject(source, game))) {
|
.anyMatch(ability -> ability.checkObject(source, game))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,7 +651,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
game.informPlayers(getLogName() + " discards down to "
|
game.informPlayers(getLogName() + " discards down to "
|
||||||
+ this.maxHandSize
|
+ this.maxHandSize
|
||||||
+ (this.maxHandSize == 1
|
+ (this.maxHandSize == 1
|
||||||
? " hand card" : " hand cards"));
|
? " hand card" : " hand cards"));
|
||||||
}
|
}
|
||||||
discard(hand.size() - this.maxHandSize, false, null, game);
|
discard(hand.size() - this.maxHandSize, false, null, game);
|
||||||
}
|
}
|
||||||
|
@ -801,7 +800,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
GameEvent gameEvent = GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD,
|
GameEvent gameEvent = GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD,
|
||||||
card.getId(), source == null
|
card.getId(), source == null
|
||||||
? null : source.getSourceId(), playerId);
|
? null : source.getSourceId(), playerId);
|
||||||
gameEvent.setFlag(source != null); // event from effect or from cost (source == null)
|
gameEvent.setFlag(source != null); // event from effect or from cost (source == null)
|
||||||
if (game.replaceEvent(gameEvent, source)) {
|
if (game.replaceEvent(gameEvent, source)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1067,12 +1066,12 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
private boolean moveObjectToLibrary(UUID objectId, UUID sourceId, Game game, boolean toTop, boolean withName) {
|
private boolean moveObjectToLibrary(UUID objectId, UUID sourceId, Game game, boolean toTop, boolean withName) {
|
||||||
MageObject mageObject = game.getObject(objectId);
|
MageObject mageObject = game.getObject(objectId);
|
||||||
if (mageObject instanceof Spell && mageObject.isCopy()) {
|
if (mageObject instanceof Spell && mageObject.isCopy()) {
|
||||||
// Spell copies are not moved as cards, so here the no copy spell has to be selected to move
|
// Spell copies are not moved as cards, so here the no copy spell has to be selected to move
|
||||||
// (but because copy and original have the same objectId the wrong sepell can be selected from stack).
|
// (but because copy and original have the same objectId the wrong sepell can be selected from stack).
|
||||||
// So let's check if the original spell is on the stack and has to be selected. // TODO: Better handling so each spell could be selected by a unique id
|
// So let's check if the original spell is on the stack and has to be selected. // TODO: Better handling so each spell could be selected by a unique id
|
||||||
Spell spellNoCopy = game.getStack().getSpell(sourceId, false);
|
Spell spellNoCopy = game.getStack().getSpell(sourceId, false);
|
||||||
if (spellNoCopy != null) {
|
if (spellNoCopy != null) {
|
||||||
mageObject = spellNoCopy;
|
mageObject = spellNoCopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mageObject != null) {
|
if (mageObject != null) {
|
||||||
|
@ -1145,6 +1144,14 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param originalAbility
|
||||||
|
* @param game
|
||||||
|
* @param noMana cast it without paying mana costs
|
||||||
|
* @param permittingObject which object permitted the cast
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(SpellAbility originalAbility, Game game, boolean noMana, MageObjectReference permittingObject) {
|
public boolean cast(SpellAbility originalAbility, Game game, boolean noMana, MageObjectReference permittingObject) {
|
||||||
if (game == null || originalAbility == null) {
|
if (game == null || originalAbility == null) {
|
||||||
|
@ -1486,7 +1493,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restoreState(bookmark, triggeredAbility.getRule(), game); // why restore is needed here? (to remove the triggered ability from the stack)
|
restoreState(bookmark, triggeredAbility.getRule(), game); // why restore is needed here? (to remove the triggered ability from the stack because of no possible targets)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2713,7 +2720,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
* @param winnable
|
* @param winnable
|
||||||
* @param appliedEffects
|
* @param appliedEffects
|
||||||
* @return if winnable, true if player won the toss, if not winnable, true
|
* @return if winnable, true if player won the toss, if not winnable, true
|
||||||
* for heads and false for tails
|
* for heads and false for tails
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean flipCoin(Ability source, Game game, boolean winnable, List<UUID> appliedEffects) {
|
public boolean flipCoin(Ability source, Game game, boolean winnable, List<UUID> appliedEffects) {
|
||||||
|
@ -2807,7 +2814,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
* @param numberPlanarSides The number of chaos sides the planar die
|
* @param numberPlanarSides The number of chaos sides the planar die
|
||||||
* currently has (normally 1)
|
* currently has (normally 1)
|
||||||
* @return the outcome that the player rolled. Either ChaosRoll, PlanarRoll
|
* @return the outcome that the player rolled. Either ChaosRoll, PlanarRoll
|
||||||
* or NilRoll
|
* or NilRoll
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PlanarDieRoll rollPlanarDie(Game game, List<UUID> appliedEffects, int numberChaosSides,
|
public PlanarDieRoll rollPlanarDie(Game game, List<UUID> appliedEffects, int numberChaosSides,
|
||||||
|
@ -2861,17 +2868,18 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the mana options the player currently has. That means which combinations of
|
* Returns the mana options the player currently has. That means which
|
||||||
* mana are available to cast spells or activate abilities etc.
|
* combinations of mana are available to cast spells or activate abilities
|
||||||
*
|
* etc.
|
||||||
|
*
|
||||||
* @param game
|
* @param game
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ManaOptions getManaAvailable(Game game) {
|
public ManaOptions getManaAvailable(Game game) {
|
||||||
boolean oldState = game.inCheckPlayableState();
|
boolean oldState = game.inCheckPlayableState();
|
||||||
game.setCheckPlayableState(true);
|
game.setCheckPlayableState(true);
|
||||||
|
|
||||||
ManaOptions availableMana = new ManaOptions();
|
ManaOptions availableMana = new ManaOptions();
|
||||||
|
|
||||||
List<Abilities<ActivatedManaAbilityImpl>> sourceWithoutManaCosts = new ArrayList<>();
|
List<Abilities<ActivatedManaAbilityImpl>> sourceWithoutManaCosts = new ArrayList<>();
|
||||||
|
@ -2913,34 +2921,37 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
|
|
||||||
// remove duplicated variants (see ManaOptionsTest for info - when that rises)
|
// remove duplicated variants (see ManaOptionsTest for info - when that rises)
|
||||||
availableMana.removeDuplicated();
|
availableMana.removeDuplicated();
|
||||||
|
|
||||||
game.setCheckPlayableState(oldState);
|
game.setCheckPlayableState(oldState);
|
||||||
return availableMana;
|
return availableMana;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used during calculation of available mana to gather the amount of producable triggered mana caused by using mana sources.
|
* Used during calculation of available mana to gather the amount of
|
||||||
* So the set value is only used during the calculation of the mana produced by one source and cleared thereafter
|
* producable triggered mana caused by using mana sources. So the set value
|
||||||
*
|
* is only used during the calculation of the mana produced by one source
|
||||||
* @param netManaAvailable the net mana produced by the triggered mana abaility
|
* and cleared thereafter
|
||||||
|
*
|
||||||
|
* @param netManaAvailable the net mana produced by the triggered mana
|
||||||
|
* abaility
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addAvailableTriggeredMana(List<Mana> netManaAvailable) {
|
public void addAvailableTriggeredMana(List<Mana> netManaAvailable) {
|
||||||
this.availableTriggeredManaList.add(netManaAvailable);
|
this.availableTriggeredManaList.add(netManaAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used during calculation of available mana to get the amount of producable triggered mana caused by using mana sources.
|
* Used during calculation of available mana to get the amount of producable
|
||||||
* The list is cleared as soon the value is retrieved during available mana calculation.
|
* triggered mana caused by using mana sources. The list is cleared as soon
|
||||||
*
|
* the value is retrieved during available mana calculation.
|
||||||
* @return
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<List<Mana>> getAvailableTriggeredMana() {
|
public List<List<Mana>> getAvailableTriggeredMana() {
|
||||||
return availableTriggeredManaList;
|
return availableTriggeredManaList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// returns only mana producers that don't require mana payment
|
// returns only mana producers that don't require mana payment
|
||||||
protected List<MageObject> getAvailableManaProducers(Game game) {
|
protected List<MageObject> getAvailableManaProducers(Game game) {
|
||||||
List<MageObject> result = new ArrayList<>();
|
List<MageObject> result = new ArrayList<>();
|
||||||
|
@ -3364,8 +3375,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
* currently cast/activate with his available ressources
|
* currently cast/activate with his available ressources
|
||||||
*
|
*
|
||||||
* @param game
|
* @param game
|
||||||
* @param hidden also from hidden objects (e.g. turned face down cards ?)
|
* @param hidden also from hidden objects (e.g. turned face
|
||||||
* @param fromZone of objects from which zone (ALL = from all zones)
|
* down cards ?)
|
||||||
|
* @param fromZone of objects from which zone (ALL = from all
|
||||||
|
* zones)
|
||||||
* @param hideDuplicatedAbilities if equal abilities exist return only the
|
* @param hideDuplicatedAbilities if equal abilities exist return only the
|
||||||
* first instance
|
* first instance
|
||||||
* @return
|
* @return
|
||||||
|
@ -3532,7 +3545,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
*
|
*
|
||||||
* @param game
|
* @param game
|
||||||
* @return A Set of cardIds that are playable and amount of playable
|
* @return A Set of cardIds that are playable and amount of playable
|
||||||
* abilities
|
* abilities
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Map<UUID, Integer> getPlayableObjects(Game game, Zone zone) {
|
public Map<UUID, Integer> getPlayableObjects(Game game, Zone zone) {
|
||||||
|
@ -4084,7 +4097,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
// identify cards from one owner
|
// identify cards from one owner
|
||||||
Cards cards = new CardsImpl();
|
Cards cards = new CardsImpl();
|
||||||
UUID ownerId = null;
|
UUID ownerId = null;
|
||||||
for (Iterator<Card> it = allCards.iterator(); it.hasNext(); ) {
|
for (Iterator<Card> it = allCards.iterator(); it.hasNext();) {
|
||||||
Card card = it.next();
|
Card card = it.next();
|
||||||
if (cards.isEmpty()) {
|
if (cards.isEmpty()) {
|
||||||
ownerId = card.getOwnerId();
|
ownerId = card.getOwnerId();
|
||||||
|
@ -4265,7 +4278,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName()
|
game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName()
|
||||||
+ (card.isCopy() ? " (Copy)" : "") : "a card face down") + ' '
|
+ (card.isCopy() ? " (Copy)" : "") : "a card face down") + ' '
|
||||||
+ (fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH)
|
+ (fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH)
|
||||||
+ ' ' : "") + "to the exile zone");
|
+ ' ' : "") + "to the exile zone");
|
||||||
|
|
||||||
}
|
}
|
||||||
result = true;
|
result = true;
|
||||||
|
|
Loading…
Reference in a new issue