* Progenitor Mimic - Fixed that the copy effect did not work correctly (fixes #958).

This commit is contained in:
LevelX2 2015-05-08 14:45:14 +02:00
parent 2b719f1dba
commit 5c041753a6
4 changed files with 126 additions and 99 deletions

View file

@ -66,8 +66,6 @@ public class ProgenitorMimic extends CardImpl {
this.expansionSetCode = "DGM";
this.subtype.add("Shapeshifter");
this.color.setBlue(true);
this.color.setGreen(true);
this.power = new MageInt(0);
this.toughness = new MageInt(0);
@ -97,6 +95,7 @@ class ProgenitorMimicApplyToPermanent extends ApplyToPermanent {
static {
filter.add(Predicates.not(new TokenPredicate()));
}
@Override
public Boolean apply(Game game, Permanent permanent) {
Ability ability = new ConditionalTriggeredAbility(
@ -127,26 +126,32 @@ class ProgenitorMimicCopyEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent copyFromPermanent = null;
// retrieve the copied permanent of Progenitor Mimic
// handle copies of copies
for (Effect effect : game.getState().getContinuousEffects().getLayeredEffects(game)) {
if (effect instanceof CopyEffect) {
CopyEffect copyEffect = (CopyEffect) effect;
// take the exiting copy effect of Progenitor Mimic
// there is another copy effect that our targetPermanent copies stats from
if (copyEffect.getSourceId().equals(source.getSourceId())) {
MageObject object = ((CopyEffect) effect).getTarget();
if (object instanceof Permanent) {
copyFromPermanent = (Permanent)object;
MageObject oldBluePrint = ((CopyEffect) effect).getTarget();
if (oldBluePrint instanceof Permanent) {
// copy it and apply the applier if any
copyFromPermanent = (Permanent) oldBluePrint;
}
}
}
}
if (copyFromPermanent != null) {
EmptyToken token = new EmptyToken();
if (copyFromPermanent == null) {
// if it was no copy of copy take the target itself
copyFromPermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
}
if (copyFromPermanent != null) {
EmptyToken token = new EmptyToken();
CardUtil.copyTo(token).from(copyFromPermanent); // needed so that entersBattlefied triggered abilities see the attributes (e.g. Master Biomancer)
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId());
Permanent sourcePermanent = game.getPermanent(token.getLastAddedToken());
if (sourcePermanent != null) {
game.copyPermanent(copyFromPermanent, sourcePermanent, source, new ProgenitorMimicApplyToPermanent());
Permanent newPermanentToken = game.getPermanent(token.getLastAddedToken());
if (newPermanentToken != null) {
game.copyPermanent(copyFromPermanent, newPermanentToken, source, null);
return true;
}
}

View file

@ -27,8 +27,6 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Anaconda");
setStopAt(4, PhaseStep.END_TURN);
execute();
@ -55,59 +53,81 @@ public class ProgenitorMimicTest extends CardTestPlayerBase {
Assert.assertEquals("Only one non token permanent ",1, nonTokens);
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.
// /**
// * Tests Clone is sacrificed and only one effect is turned on
// */
// @Test
// public void testCloneSacrifice() {
// addCard(Zone.BATTLEFIELD, playerA, "Bloodgift Demon", 1);
//
// addCard(Zone.HAND, playerA, "Diabolic Edict");
// addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
//
// addCard(Zone.HAND, playerB, "Clone");
// addCard(Zone.BATTLEFIELD, playerB, "Island", 4);
//
// castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clone");
// castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Diabolic Edict", playerB);
//
// setStopAt(4, PhaseStep.END_TURN);
// execute();
//
// assertPermanentCount(playerA, "Bloodgift Demon", 1);
// assertGraveyardCount(playerA, "Diabolic Edict", 1);
// assertPermanentCount(playerB, "Bloodgift Demon", 0);
// assertGraveyardCount(playerB, "Clone", 1);
//
// // 1 from draw steps + 2 from Demon
// assertHandCount(playerA, 3);
// // 2 from draw steps + no from Demon (should be sacrificed)
// assertHandCount(playerB, 2);
//
// assertLife(playerA, 18);
// assertLife(playerB, 20);
// }
//
// @Test
// public void testCard3() {
// addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
// addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
// addCard(Zone.HAND, playerA, "Public Execution");
// addCard(Zone.HAND, playerA, "Clone");
//
// addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves");
// addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm");
//
// castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Executio", "Llanowar Elves");
// castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Clone");
//
// setStopAt(1, PhaseStep.END_TURN);
// execute();
//
// assertPermanentCount(playerB, "Llanowar Elves", 0);
// assertPowerToughness(playerB, "Craw Wurm", 4, 4);
// assertPowerToughness(playerA, "Craw Wurm", 6, 4);
// }
*/
@Test
public void testTwoMimic() {
addCard(Zone.BATTLEFIELD, playerA, "Runeclaw Bear", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
// Return target permanent you control to its owner's hand. You gain 4 life.
addCard(Zone.HAND, playerA, "Narrow Escape");
// 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", 2);
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
addCard(Zone.BATTLEFIELD, playerB, "Forest", 3);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
setChoice(playerB, "Runeclaw Bear");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Narrow Escape", "Runeclaw Bear");
// Begin of upkeep 1 token added
castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Progenitor Mimic");
setChoice(playerB, "Runeclaw Bear");
// Begin of upkeep 3 tokens added
setStopAt(6, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 24);
assertLife(playerB, 20);
assertGraveyardCount(playerA, "Narrow Escape", 1);
assertPermanentCount(playerA, "Runeclaw Bear", 0);
assertHandCount(playerA, "Runeclaw Bear", 1);
assertPermanentCount(playerB, "Runeclaw Bear", 6);
int tokens = 0;
int nonTokens = 0;
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
if (permanent.getControllerId().equals(playerB.getId())) {
if (permanent.getCardType().contains(CardType.CREATURE)) {
if (permanent instanceof PermanentToken) {
tokens++;
} else {
nonTokens++;
}
}
}
}
Assert.assertEquals("Two non token permanents ",2, nonTokens);
Assert.assertEquals("Four token permanents",4, tokens);
}
}

View file

@ -1285,46 +1285,47 @@ public abstract class GameImpl implements Game, Serializable {
@Override
public Permanent copyPermanent(Duration duration, Permanent copyFromPermanent, Permanent copyToPermanent, Ability source, ApplyToPermanent applier) {
Permanent permanent = copyFromPermanent.copy();
//getState().addCard(permanent);
permanent.reset(this);
if (copyFromPermanent.isMorphed() || copyFromPermanent.isManifested()) {
MorphAbility.setPermanentToFaceDownCreature(permanent);
}
permanent.assignNewId();
if (copyFromPermanent.isTransformed()) {
TransformAbility.transform(permanent, copyFromPermanent.getSecondCardFace(), this);
}
applier.apply(this, permanent);
CopyEffect newEffect = new CopyEffect(duration, permanent, copyToPermanent.getId());
newEffect.newId();
newEffect.setApplier(applier);
Ability newAbility = source.copy();
newEffect.init(newAbility, this);
Permanent newBluePrint = null;
// handle copies of copies
for (Effect effect : getState().getContinuousEffects().getLayeredEffects(this)) {
if (effect instanceof CopyEffect) {
CopyEffect copyEffect = (CopyEffect) effect;
// there is another copy effect that our targetPermanent copies stats from
if (copyEffect.getSourceId().equals(copyFromPermanent.getId())) {
MageObject object = ((CopyEffect) effect).getTarget();
if (object instanceof Permanent) {
// so we will use original card instead of target
Permanent original = (Permanent)object;
// copy it and apply changes we need
original = original.copy();
applier.apply(this, original);
newEffect.setTarget(object);
MageObject oldBluePrint = ((CopyEffect) effect).getTarget();
if (oldBluePrint instanceof Permanent) {
// copy it and apply the applier if any
newBluePrint = ((Permanent)oldBluePrint).copy();
}
}
}
}
// if it was no copy of copy take the target itself
if (newBluePrint == null) {
newBluePrint = copyFromPermanent.copy();
newBluePrint.reset(this);
//getState().addCard(permanent);
if (copyFromPermanent.isMorphed() || copyFromPermanent.isManifested()) {
MorphAbility.setPermanentToFaceDownCreature(newBluePrint);
}
newBluePrint.assignNewId();
if (copyFromPermanent.isTransformed()) {
TransformAbility.transform(newBluePrint, copyFromPermanent.getSecondCardFace(), this);
}
}
if (applier != null) {
applier.apply(this, newBluePrint);
}
CopyEffect newEffect = new CopyEffect(duration, newBluePrint, copyToPermanent.getId());
newEffect.newId();
newEffect.setApplier(applier);
Ability newAbility = source.copy();
newEffect.init(newAbility, this);
state.addEffect(newEffect, newAbility);
return permanent;
return newBluePrint;
}
@Override

View file

@ -209,7 +209,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
this.maxBlockedBy = 0;
this.copy = false;
}
@Override
public String getValue() {
StringBuilder sb = threadLocalBuilder.get();
@ -516,8 +516,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
if (!phasedIn) {
if (!replaceEvent(EventType.PHASE_IN, game)) {
this.phasedIn = true;
if (!game.isSimulation())
if (!game.isSimulation()) {
game.informPlayers(getLogName() + " phased in");
}
fireEvent(EventType.PHASED_IN, game);
return true;
}
@ -1345,4 +1346,4 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
fightTarget.damage(getPower().getValue(), getId(), game, false, true);
return true;
}
}
}