Added test.

This commit is contained in:
LevelX2 2016-03-07 18:30:58 +01:00
parent 0a31a8b479
commit d7ae1c51c9
4 changed files with 126 additions and 57 deletions

View file

@ -1,16 +1,16 @@
/* /*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, are * Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met: * permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, this list of * 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer. * conditions and the following disclaimer.
* *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list * 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials * of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution. * provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
@ -20,22 +20,14 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* The views and conclusions contained in the software and documentation are those of the * The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.sets.magic2011; package mage.sets.magic2011;
import java.util.UUID; import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
@ -44,6 +36,13 @@ import mage.abilities.costs.common.TapTargetCost;
import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
@ -77,7 +76,10 @@ public class CaptivatingVampire extends CardImpl {
this.power = new MageInt(2); this.power = new MageInt(2);
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Other Vampire creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter1, true))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter1, true)));
// Tap five untapped Vampires you control: Gain control of target creature. It becomes a Vampire in addition to its other types.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CaptivatingVampireEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(5, 5, filter2, true))); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CaptivatingVampireEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(5, 5, filter2, true)));
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability); this.addAbility(ability);
@ -97,7 +99,7 @@ public class CaptivatingVampire extends CardImpl {
class CaptivatingVampireEffect extends ContinuousEffectImpl { class CaptivatingVampireEffect extends ContinuousEffectImpl {
public CaptivatingVampireEffect() { public CaptivatingVampireEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment); super(Duration.Custom, Outcome.Detriment);
staticText = "Gain control of target creature. It becomes a Vampire in addition to its other types"; staticText = "Gain control of target creature. It becomes a Vampire in addition to its other types";
} }
@ -112,7 +114,7 @@ class CaptivatingVampireEffect extends ContinuousEffectImpl {
@Override @Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent permanent = game.getPermanent(source.getFirstTarget()); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) { if (permanent != null) {
switch (layer) { switch (layer) {
case ControlChangingEffects_2: case ControlChangingEffects_2:
@ -122,12 +124,15 @@ class CaptivatingVampireEffect extends ContinuousEffectImpl {
break; break;
case TypeChangingEffects_4: case TypeChangingEffects_4:
if (sublayer == SubLayer.NA) { if (sublayer == SubLayer.NA) {
permanent.getSubtype().add("Vampire"); if (!permanent.getSubtype().contains("Vampire")) {
permanent.getSubtype().add("Vampire");
}
} }
break; break;
} }
return true; return true;
} }
discard();
return false; return false;
} }
@ -138,7 +143,7 @@ class CaptivatingVampireEffect extends ContinuousEffectImpl {
@Override @Override
public boolean hasLayer(Layer layer) { public boolean hasLayer(Layer layer) {
return layer == Layer.ControlChangingEffects_2 || layer == layer.TypeChangingEffects_4; return layer == Layer.ControlChangingEffects_2 || layer == Layer.TypeChangingEffects_4;
} }
} }

View file

@ -1,7 +1,9 @@
package org.mage.test.cards.copy; package org.mage.test.cards.copy;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.Filter;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken; import mage.game.permanent.PermanentToken;
import org.junit.Assert; import org.junit.Assert;
@ -36,43 +38,49 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Runeclaw Bear", 1); assertPermanentCount(playerA, "Runeclaw Bear", 1);
assertPermanentCount(playerB, "Runeclaw Bear", 2); assertPermanentCount(playerB, "Runeclaw Bear", 2);
int tokens = 0; int tokens = 0;
int nonTokens = 0; int nonTokens = 0;
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) { for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
if (permanent.getControllerId().equals(playerB.getId())) { if (permanent.getControllerId().equals(playerB.getId())) {
if (permanent.getCardType().contains(CardType.CREATURE)) { if (permanent.getCardType().contains(CardType.CREATURE)) {
if (permanent instanceof PermanentToken) { if (permanent instanceof PermanentToken) {
tokens++; tokens++;
} else { } else {
nonTokens++; nonTokens++;
} }
} }
} }
} }
Assert.assertEquals("Only one non token permanent ",1, nonTokens); Assert.assertEquals("Only one non token permanent ", 1, nonTokens);
Assert.assertEquals("Only one token permanent ",1, tokens); Assert.assertEquals("Only one token permanent ", 1, tokens);
} }
/**
* If you have Progenitor Mimic copy a creature it gets all of the abilities plus "At the beginning of upkeep
* if this creature isn't a token, put a token that's a copy of this creature".
* Up to this point everything works correctly.
*
* If you then summon another mimic and have it be a copy of the first mimic it should have "At the beginning of
* upkeep if this creature isn't a token, put a token that's a copy of this creature" two times. The second mimic
* would then make two copies and the first mimic would make one copy every turn. Right now the second mimc only
* makes one copy per turn.
*
* 706.9a Some copy effects cause the copy to gain an ability as part of the copying process. This ability becomes
* part of the copiable values for the copy, along with any other abilities that were copied.
* Example: Quirion Elves enters the battlefield and an Unstable Shapeshifter copies it. The copiable values of the
* Shapeshifter now match those of the Elves, except that the Shapeshifter also has the ability Whenever a creature
* enters the battlefield, Unstable Shapeshifter becomes a copy of that creature and gains this ability. Then a Clone
* enters the battlefield as a copy of the Unstable Shapeshifter. The Clone copies the new copiable values of the
* Shapeshifter, including the ability that the Shapeshifter gave itself when it copied the Elves.
/**
* If you have Progenitor Mimic copy a creature it gets all of the abilities
* plus "At the beginning of upkeep if this creature isn't a token, put a
* token that's a copy of this creature". Up to this point everything works
* correctly.
*
* If you then summon another mimic and have it be a copy of the first mimic
* it should have "At the beginning of upkeep if this creature isn't a
* token, put a token that's a copy of this creature" two times. The second
* mimic would then make two copies and the first mimic would make one copy
* every turn. Right now the second mimc only makes one copy per turn.
*
* 706.9a Some copy effects cause the copy to gain an ability as part of the
* copying process. This ability becomes part of the copiable values for the
* copy, along with any other abilities that were copied. Example: Quirion
* Elves enters the battlefield and an Unstable Shapeshifter copies it. The
* copiable values of the Shapeshifter now match those of the Elves, except
* that the Shapeshifter also has the ability Whenever a creature enters
* the battlefield, Unstable Shapeshifter becomes a copy of that creature
* and gains this ability. Then a Clone enters the battlefield as a copy of
* the Unstable Shapeshifter. The Clone copies the new copiable values of
* the Shapeshifter, including the ability that the Shapeshifter gave itself
* when it copied the Elves.
*
*/ */
@Test @Test
public void testTwoMimic() { public void testTwoMimic() {
@ -81,7 +89,7 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
// Return target permanent you control to its owner's hand. You gain 4 life. // Return target permanent you control to its owner's hand. You gain 4 life.
addCard(Zone.HAND, playerA, "Narrow Escape"); addCard(Zone.HAND, playerA, "Narrow Escape");
// You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield except // You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield except
// it gains "At the beginning of your upkeep, if this creature isn't a token, put a token onto the battlefield // it gains "At the beginning of your upkeep, if this creature isn't a token, put a token onto the battlefield
// that's a copy of this creature." // that's a copy of this creature."
addCard(Zone.HAND, playerB, "Progenitor Mimic", 2); addCard(Zone.HAND, playerB, "Progenitor Mimic", 2);
@ -90,9 +98,9 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
setChoice(playerB, "Runeclaw Bear"); setChoice(playerB, "Runeclaw Bear");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Narrow Escape", "Runeclaw Bear"); castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Narrow Escape", "Runeclaw Bear");
// Begin of upkeep 1 token added // Begin of upkeep 1 token added
castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic"); castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
setChoice(playerB, "Runeclaw Bear"); setChoice(playerB, "Runeclaw Bear");
@ -107,27 +115,71 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Narrow Escape", 1); assertGraveyardCount(playerA, "Narrow Escape", 1);
assertPermanentCount(playerA, "Runeclaw Bear", 0); assertPermanentCount(playerA, "Runeclaw Bear", 0);
assertHandCount(playerA, "Runeclaw Bear", 1); assertHandCount(playerA, "Runeclaw Bear", 1);
assertPermanentCount(playerB, "Runeclaw Bear", 6); assertPermanentCount(playerB, "Runeclaw Bear", 6);
int tokens = 0; int tokens = 0;
int nonTokens = 0; int nonTokens = 0;
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) { for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
if (permanent.getControllerId().equals(playerB.getId())) { if (permanent.getControllerId().equals(playerB.getId())) {
if (permanent.getCardType().contains(CardType.CREATURE)) { if (permanent.getCardType().contains(CardType.CREATURE)) {
if (permanent instanceof PermanentToken) { if (permanent instanceof PermanentToken) {
tokens++; tokens++;
} else { } else {
nonTokens++; nonTokens++;
} }
} }
} }
} }
Assert.assertEquals("Two non token permanents ",2, nonTokens); Assert.assertEquals("Two non token permanents ", 2, nonTokens);
Assert.assertEquals("Four token permanents",4, tokens); Assert.assertEquals("Four token permanents", 4, tokens);
} }
/**
* In a Commander FFA game, I controlled 5 vampires (one of which was
* Captivating Vampire). My opponent cast Progenitor Mimic, copying
* Captivating Vampire. I used the ability of my Captivating Vampire to gain
* control of his Mimic/Vampire but the buff didn't switch control. His
* other vampire still got the buff even after I gained control of the
* Mimic/Vampire.
*
* Did not get to see if the Mimic/Vampire produced tokens on the right side
* of the field (my side) as the game ended just after my turn.
*/
@Test
public void testChangeControl() {
// Other Vampire creatures you control get +1/+1.
// Tap five untapped Vampires you control: Gain control of target creature. It becomes a Vampire in addition to its other types.
addCard(Zone.BATTLEFIELD, playerA, "Captivating Vampire", 1); // 2/2
// Lifelink
addCard(Zone.BATTLEFIELD, playerA, "Child of Night", 4); // 2/1
// You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield except
// it gains "At the beginning of your upkeep, if this creature isn't a token, put a token onto the battlefield
// that's a copy of this creature."
addCard(Zone.HAND, playerB, "Progenitor Mimic", 1);
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
addCard(Zone.BATTLEFIELD, playerB, "Forest", 3);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
setChoice(playerB, "Captivating Vampire");
activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tap five untapped Vampire", "Captivating Vampire[only copy]");
setChoice(playerA, "Captivating Vampire");
setChoice(playerA, "Child of Night");
setChoice(playerA, "Child of Night");
setChoice(playerA, "Child of Night");
setChoice(playerA, "Child of Night");
setStopAt(2, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Captivating Vampire", 2);
assertPowerToughness(playerA, "Captivating Vampire", 3, 3, Filter.ComparisonScope.All); // +1 from the other Captivating Vampire
assertPowerToughness(playerA, "Child of Night", 4, 3, Filter.ComparisonScope.All); // +2 from the two Captivating Vampire
}
} }

View file

@ -318,10 +318,23 @@ public class TestPlayer implements Player {
} }
} }
} else { } else {
boolean originOnly = false;
boolean copyOnly = false;
if (targetName.endsWith("]")) {
if (targetName.endsWith("[no copy]")) {
originOnly = true;
targetName = targetName.substring(0, targetName.length() - 9);
}
if (targetName.endsWith("[only copy]")) {
copyOnly = true;
targetName = targetName.substring(0, targetName.length() - 11);
}
}
for (UUID id : currentTarget.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) { for (UUID id : currentTarget.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) {
if (!currentTarget.getTargets().contains(id)) { if (!currentTarget.getTargets().contains(id)) {
MageObject object = game.getObject(id); MageObject object = game.getObject(id);
if (object != null if (object != null
&& ((object.isCopy() && !originOnly) || (!object.isCopy() && !copyOnly))
&& ((!targetName.isEmpty() && object.getName().startsWith(targetName)) || (targetName.isEmpty() && object.getName().isEmpty()))) { && ((!targetName.isEmpty() && object.getName().startsWith(targetName)) || (targetName.isEmpty() && object.getName().isEmpty()))) {
if (currentTarget.getNumberOfTargets() == 1) { if (currentTarget.getNumberOfTargets() == 1) {
currentTarget.clearChosen(); currentTarget.clearChosen();

View file

@ -27,7 +27,6 @@
*/ */
package mage.abilities.costs.common; package mage.abilities.costs.common;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
@ -52,7 +51,7 @@ public class TapTargetCost extends CostImpl {
this.text this.text
= new StringBuilder("Tap ") = new StringBuilder("Tap ")
.append((target.getTargetName().startsWith("a ") || target.getTargetName().startsWith("an ") || target.getTargetName().startsWith("another")) .append((target.getTargetName().startsWith("a ") || target.getTargetName().startsWith("an ") || target.getTargetName().startsWith("another"))
? "" : CardUtil.numberToText(target.getMaxNumberOfTargets()) + " ") ? "" : CardUtil.numberToText(target.getMaxNumberOfTargets()) + " ")
.append(target.getTargetName()).toString(); .append(target.getTargetName()).toString();
} }
@ -64,7 +63,7 @@ public class TapTargetCost extends CostImpl {
@Override @Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
if (target.choose(Outcome.Tap, controllerId, sourceId, game)) { if (target.choose(Outcome.Tap, controllerId, sourceId, game)) {
for (UUID targetId : (List<UUID>) target.getTargets()) { for (UUID targetId : target.getTargets()) {
Permanent permanent = game.getPermanent(targetId); Permanent permanent = game.getPermanent(targetId);
if (permanent == null) { if (permanent == null) {
return false; return false;